วิธีจัดการไฟล์จำนวนมากในเชลล์?


9

$ ls ./dir_with_huge_amount_of_files/errors/

สมมติว่าไดเรกทอรีเต็มไปด้วยรูปภาพที่มียูนิกซ์ประทับเวลาฉันหมายถึงมีหน่วยวัดเป็นกิกะไบต์หรือมากกว่านั้น คำสั่งเชลล์เช่นlsจะได้รับคำเตือนแบบล้นเนื่องจากไม่ได้ออกแบบมาให้ทำงานกับรูปภาพนับล้าน (หรือมากกว่า) ฉันจะจัดการไฟล์จำนวนมากได้อย่างไร ตัวอย่างเช่นถ้าฉันต้องการค้นหารูปภาพที่อยู่ตรงกลาง (ตามเวลาในชื่อและเวลาสร้าง) มีระบบไฟล์บางส่วนที่มีคุณสมบัติการค้นหาในตัวหรือไม่? คุณจะใช้คำสั่งใด ฉันพยายามอย่างสบายlsและfindด้วยการตั้งค่าสถานะที่จำเป็น แต่พวกเขาก็ช้ามากหรือสร้างคำเตือนดังนั้นฉันคิดว่าฉันต้องการระบบไฟล์หรือ db ที่ดีกว่าหรืออะไรทำนองนั้นเพื่อจัดทำดัชนีรูปภาพ โดยทั่วไปฉันต้องการอาร์เรย์หนึ่งชุดที่จะจัดวางรูปภาพ inodes ตามลำดับเวลา ทำอย่างไร ต่อมาสามารถเพิ่มข้อมูลเมตาที่มียูนิกซ์ - เวลา

[Update]

มีข้อบกพร่องที่ร้ายแรงในคำตอบปัจจุบันผู้คนเพียงโพสต์เรียงลำดับของคำตอบโดยไม่ต้องทดสอบเชิงประจักษ์ หากพวกเขาทดสอบข้อเสนอแนะของพวกเขาพวกเขาอาจจะล้มเหลว ดังนั้นฉันจึงสร้างเครื่องมือบรรทัดคำสั่งให้คุณซึ่งคุณสามารถสร้างแซนด์บ็อกซ์เพื่อสร้างไฟล์จำนวนมากและทดสอบข้อเสนอแนะของคุณเช่นเดียวกับไฟล์จำนวน 1e7 อาจใช้เวลานานในการสร้างไฟล์ดังนั้นต้องอดทน หากมีคนรู้วิธีที่รวดเร็วกว่านี้โปรดแก้ไขรหัส พิมพ์python code.py --helpเพื่อรับความช่วยเหลือ มีความสุข!

ตัวอย่างการใช้งานเพื่อสร้างไฟล์ dirred จำนวนมาก

$ ls ./data2
ls: ./data2: No such file or directory
$ python testFill.py -n 3 -d 7                                                 
$ tree data2/                                                                  
data2/
|-- 0
|   |-- 1302407302636973
|   |-- 1302407302638022
|   `-- 1302407302638829
|-- 1
|   |-- 1302407302639604
|   |-- 1302407302641652
|   `-- 1302407302642399
|-- 2
|   |-- 1302407302643158
|   |-- 1302407302645223
|   `-- 1302407302646026
|-- 3
|   |-- 1302407302646837
|   |-- 1302407302649110
|   `-- 1302407302649944
|-- 4
|   |-- 1302407302650771
|   |-- 1302407302652921
|   `-- 1302407302653685
|-- 5
|   |-- 1302407302654423
|   |-- 1302407302656352
|   `-- 1302407302656992
`-- 6
    |-- 1302407302657652
    |-- 1302407302659543
    `-- 1302407302660156

7 directories, 21 files

รหัส testFill.py

# Author: hhh
# License: ISC license

import os, math, time, optparse, sys

def createHugeAmountOfFiles(fileAmount, dirAmount):
   counter = 0
   DENSITY = 1e7
   dir = "./data/"

   do = dir+str(counter)+"/"
   while (os.path.exists(do)):
      counter = counter+1
      do = dir+str(counter)+"/"

   os.mkdir(do)

   for d in range(int(dirAmount)):
      for f in range(int(fileAmount)):
         timeIt = int(time.time()*1e6)
         if (not os.path.exists(do)):
            os.mkdir(do)

         if (timeIt % DENSITY == 0):
            counter = counter+1
            do = dir+str(counter)+"/"

            if (not os.path.exists(do)):
               os.mkdir(do)


         do = dir+str(counter)+"/"
         if(not os.path.exists(do)):
            os.mkdir(do)

         f = open(do+str(timeIt), 'w')
         f.write("Automatically created file to test Huge amount of files.")
         f.close()
      counter = counter +1


def ls(dir):
   for root, dirs, files in os.walk("./data/"+dir):
      print(files)

def rm(dir):
   for root, dirs, files in os.walk("./data/"+dir):
      for f in files:
         os.remove("./data/"+dir+"/"+f)


def parseCli():
   parser = optparse.OptionParser()
   parser.add_option("-f", "--file", dest="filename",
                     help="Location to remove files only in ./Data.", metavar="FILE")
   parser.add_option("-n", "--number", dest="number",
                     help="Number of files to generate", metavar="NUMBER")
   parser.add_option("-r", "--remove", dest="remove",
                     help="Data -dir content to remove", metavar="NUMBER")
   parser.add_option("-d", "--dir", dest="dir",
                     help="Amount of dirs to generate", metavar="NUMBER")
   parser.add_option("-q", "--quiet",
                     action="store_false", dest="verbose", default=True,
                     help="don't print status messages to stdout")

   return parser.parse_args()

def main():
   (options, args) = parseCli()

   if (options.filename):
      ls(options.filename)
   if (options.number and options.dir):
      createHugeAmountOfFiles(options.number, options.dir)
   if (options.remove):
      rm(options.remove)


main()

2
@hhh สำหรับชุดข้อมูลในระดับนี้ db-ed-db ที่ถูกต้องน่าจะเป็นตัวเลือกเดียว
xenoterracide

@xenoterracide: แต่แม้ dbs จะต้องดำเนินการค้นหาอย่างรวดเร็วด้วยบางสิ่งบางอย่างเช่นอาร์เรย์ db ฟังก์ชั่น overkill แหล่งที่มาสำหรับสิ่งที่ถ่ายภาพอยู่ที่นี่: github.com/fsphil/fswebcam บางทีฉันสามารถแก้ไขมันสักครู่เพื่อบันทึกรูปภาพดังนั้นฉันสามารถต่อท้ายบรรทัดที่มีหมายเลข inode & unix-time-stamp ลงในไฟล์ ตอนนี้ไม่ได้มีรูปภาพ แต่เป็นบรรทัดมันจะเร็วกว่ามากในการค้นหารูปภาพ หรือง่ายยิ่งขึ้นทุกครั้งที่มีการบันทึกรูปภาพลงดิสก์ฉันจะเพิ่มบรรทัดลงในไฟล์ที่มีการระบุเวลา วิธีแก้ปัญหารอบ แต่จะไม่แก้ปัญหาด้วยรูปภาพปัจจุบันดังนั้นจึงมีคำถามที่เกี่ยวข้อง

@hhh คุณใช้ระบบแฟ้มแบบใด หรือยังไม่เป็นไร ... ext มีคุณสมบัติบางอย่างในการเพิ่มประสิทธิภาพซึ่งอาจไม่ได้เปิดใช้งานตามค่าเริ่มต้น แม้ว่าสิ่งเหล่านั้นอาจไม่ได้อยู่ในระดับที่คุณกำลังพูดถึง ฐานข้อมูลได้รับการปรับให้เหมาะสมสำหรับสิ่งเหล่านี้และมีโซลูชันการจัดทำดัชนีที่หลากหลายเพื่อจัดการกับพวกเขา ตัวอย่างเช่นดัชนี btree ไม่ได้เป็นเพียงอาเรย์ง่ายๆ ...
xenoterracide

@xenoterracide: ext3 ไม่แน่ใจว่ามันสำคัญหรือไม่ ฉันคิดว่าวิธีที่ฉันแสดงให้เห็นจะช่วยแก้ไขปัญหาสำหรับปัญหาการค้นหาในอนาคต แต่มันไม่ได้ช่วยอะไรเลยกับรูปภาพปัจจุบันมันใช้เวลานานมากในการค้นหา

1
คุณมีไฟล์หลายล้านไฟล์ในไดเรกทอรีเดียวหรือไม่? หากเป็นเช่นนั้นคุณอาจพิจารณาแยกย่อยด้วยส่วนลึกหนึ่งหรือสองระดับโดยพิจารณาจากตัวอักษรตัวแรกของชื่อไฟล์เช่น:a/b/abcdef.jpg
alex

คำตอบ:


4

ลองเปลือกอื่น ฉันขอแนะนำให้ลองzshเช่นและดูว่ามันอนุญาตให้พารามิเตอร์เพิ่มเติม

ถ้าฉันเข้าใจถูกต้องส่วนหนึ่งของชื่อไฟล์เป็นเวลาประทับของ UNIX อาจแนะนำให้แบ่งไฟล์ออกเป็นโฟลเดอร์ หากรูปแบบวันที่ / เวลาเป็นหมายเลขยุค UNIX ให้ใส่เศษส่วนของจำนวนนั้นพูด 10,000's ในโฟลเดอร์แยก

หากการประทับเวลาISO 8601เป็นส่วนหนึ่งของชื่อไฟล์ให้หารด้วยปีเดือนหรือวัน


1
ls และ find ไม่ใช่ builtins ใน bash หรือ zsh ดังนั้นจึงไม่ชัดเจนว่าการสลับเชลล์จะช่วยได้อย่างไรในกรณีนี้
Robin Green

มันเกี่ยวกับการขยายตัวของเชลล์ หากเปลือกไม่สามารถขยายความโค้งได้นี่อาจเป็นปัญหา
polemon

ฉันทำไม่กี่ทดสอบใช้คำสั่งที่เกี่ยวกับ 1e6 ไฟล์ ZSH "$ cp * Test/ ksh: cp: Argument list too long % rm * zsh: sure you want to delete all the files in /home/user/Downloads [yn]? y zsh: argument list too long: rm % ls * zsh: argument list too long: ls "ประสบปัญหาเหมือนกัน: ขออภัยที่ฉันไม่สามารถเห็นว่าสิ่งนี้เกี่ยวข้องกับคำถาม -1 เพราะง่ายต่อการทดสอบสร้างไฟล์เพียง 1e6 และเรียกใช้คำสั่ง

1

จะlocate(และแน่นอนupdatedb) จะช่วยให้คุณหรือไม่?


1
updatedbfindการใช้งาน
dave1010

@ dave1010 แน่นอน แต่มันทำในพื้นหลังเป็นครั้งคราวดังนั้นถ้าเป็นที่ยอมรับของ OP ที่ไม่จำเป็นต้องอัปเดตทุกนาที แต่อาจจะวันละครั้งจากนั้นกำหนดเวลา updatedb ในเวลาที่เงียบสงบ (หรือ มีการอัปเดตกำหนดการบ่อยครั้ง แต่มีลำดับความสำคัญต่ำซึ่งเป็นสิ่งที่ควรจะเป็นอย่างไรก็ตาม) การใช้ค้นหานั้นรวดเร็วมากในการค้นหาสิ่งที่คุณต้องการ ดังนั้นคำถามสำคัญคือวิธีการที่ DB (หรือดัชนีสำหรับระบบดังกล่าวอื่น ๆ ) ที่ทันสมัยจะต้องมี
asoundmove
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.