Làm thế nào để quản lý số lượng lớn các tập tin trong shell?


9

$ ls ./dir_with_huge_amount_of_files/errors/

Giả sử một thư mục chứa đầy hình ảnh với dấu thời gian unix, ý tôi là rất nhiều được đo bằng nhiều GB hoặc thậm chí nhiều hơn. Các lệnh như Shell lssẽ nhận được các cảnh báo kiểu tràn vì chúng không được thiết kế để hoạt động với hàng triệu (hoặc nhiều hơn) hình ảnh. Làm thế nào tôi có thể quản lý số lượng lớn các tập tin như vậy? Ví dụ, nếu tôi muốn tìm ảnh ở giữa (theo dấu thời gian trong tên và thời gian tạo), có một số hệ thống tệp cung cấp tính năng tìm kiếm tích hợp không? Những lệnh nào bạn sẽ sử dụng? Tôi đã thử thoải mái lsfindvới các cờ cần thiết nhưng chúng là các cảnh báo rất chậm hoặc được tạo nên tôi nghĩ rằng tôi cần hệ thống tệp hoặc db tốt hơn hoặc một cái gì đó tương tự để lập chỉ mục trước cho các hình ảnh. Về cơ bản tôi cần một mảng mà các nút của ảnh nên được đặt theo thứ tự thời gian. Làm thế nào để làm điều đó? Sau đó, siêu dữ liệu với dấu thời gian unix có thể được thêm vào.

[Cập nhật]

Có một lỗ hổng nghiêm trọng trong các câu trả lời hiện tại, mọi người chỉ đăng các loại câu trả lời mà không cần kiểm tra theo kinh nghiệm. Nếu họ đã thử nghiệm đề xuất của họ, họ có thể sẽ thất bại. Do đó, tôi đã tạo cho bạn một công cụ dòng lệnh để bạn có thể tạo hộp cát để tạo số lượng tệp khổng lồ và kiểm tra các đề xuất của bạn như với số lượng tệp 1e7. Có thể mất nhiều thời gian để tạo các tệp vì vậy hãy kiên nhẫn. Nếu ai đó biết cách nhanh hơn để làm điều này, xin vui lòng chỉnh sửa mã. Gõ python code.py --helpđể được giúp đỡ. Chúc vui vẻ!

Ví dụ sử dụng để tạo rất nhiều tập tin 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

Mã 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 đối với tập dữ liệu theo thang đo này, db index-ed đúng có lẽ là lựa chọn duy nhất
xenoterracide

@xenoterracide: nhưng ngay cả dbs cũng phải thực hiện tìm kiếm nhanh với thứ gì đó như mảng, db nghe có vẻ quá mức. Nguồn để chụp ảnh là ở đây: github.com/fsphil/fswebcam . Có lẽ, tôi có thể sửa đổi nó một chút thời gian nó lưu hình ảnh để tôi có thể nối thêm một dòng có inode-number & unix-time-tem vào tập tin. Bây giờ không phải với hình ảnh mà là dòng, nó sẽ nhanh hơn nhiều để tìm kiếm hình ảnh. Hoặc thậm chí dễ dàng hơn, mỗi khi một hình ảnh được lưu vào đĩa, tôi sẽ nối một dòng vào một tệp có dấu thời gian của nó. Giải pháp xung quanh. Nhưng sẽ không giải quyết vấn đề với hình ảnh hiện tại để câu hỏi có liên quan.

@hhh bạn đang sử dụng hệ thống tập tin nào? hoặc không phải là vấn đề chưa ... ext có một số tính năng nâng cao hiệu suất có thể không được bật theo mặc định. Mặc dù những người có lẽ sẽ không giải quyết trên quy mô mà bạn đang nói. DB được tối ưu hóa cho những điều này và có các giải pháp lập chỉ mục khác nhau để đối phó với chúng. ví dụ: chỉ số btree không chỉ là một mảng đơn giản ...
xenoterracide

@xenoterracide: ext3, không chắc nó có quan trọng hay không. Tôi nghĩ rằng giải pháp mà tôi đã minh họa khắc phục sự cố cho vấn đề tìm kiếm trong tương lai nhưng nó không giúp ích gì cho các bức ảnh hiện tại, việc tìm kiếm nó rất tốn thời gian.

1
Bạn có hàng triệu tệp trong một thư mục không? Nếu vậy, bạn có thể xem xét phân tách chúng bằng các thư mục con sâu một hoặc hai cấp, dựa trên ký tự đầu tiên của tên tệp, ví dụ:a/b/abcdef.jpg
alex

Câu trả lời:


4

Hãy thử một vỏ khác. Tôi khuyên bạn nên thử zsh chẳng hạn, và xem liệu nó có cho phép nhiều tham số hơn không.

Nếu tôi hiểu chính xác, một phần của tên tệp là dấu thời gian UNIX. Có thể nên chia các tệp thành các thư mục. Nếu định dạng ngày / giờ là số epoch UNIX, hãy đặt các phân số của số đó, giả sử 10000, trong một thư mục riêng.

Nếu dấu thời gian ISO 8601 là một phần của tên tệp, chỉ cần chia theo năm, tháng hoặc ngày.


1
ls và find không được tích hợp trong bash hoặc zsh, vì vậy không rõ việc chuyển đổi shell sẽ giúp ích như thế nào trong trường hợp này.
Robin Green

Đó là về việc mở rộng vỏ. Nếu vỏ không thể mở rộng toàn cầu, đây có thể là vấn đề.
Polemon

Tôi đã thực hiện một vài thử nghiệm chạy các lệnh trên khoảng 1e6 tệp, ZSH phải đối mặt với cùng một vấn đề : "$ 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 ". Xin lỗi nhưng tôi không thể thấy điều này có liên quan đến câu hỏi -1 vì rất dễ kiểm tra điều này, chỉ tạo các tệp 1e6 và chạy các lệnh.

1

Sẽ locate(và tất nhiên updatedb) là của bất kỳ sự giúp đỡ đối với bạn?


1
updatedbsử dụng find.
dave1010

@ dave1010, chắc chắn, nhưng thỉnh thoảng nó vẫn hoạt động ở chế độ nền, vì vậy nếu OP chấp nhận để không cần cập nhật mỗi phút, nhưng có thể mỗi ngày một lần, sau đó lên lịch cập nhật vào một giờ yên tĩnh (hoặc lên lịch cập nhật thường xuyên nhưng với mức độ ưu tiên thấp, đó là những gì nó nên có dù sao), sau đó sử dụng định vị rất nhanh để tìm thấy những gì bạn muốn. Vì vậy, câu hỏi quan trọng là làm thế nào để cập nhật DB (hoặc chỉ mục cho bất kỳ hệ thống nào khác).
asoundmove
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.