Как управлять огромным количеством файлов в оболочке?

9

$ ls ./dir_with_huge_amount_of_files/errors/

Предположим, что каталог полон картинок с метками времени Unix, я имею в виду много измеренных во многих ГБ или даже больше. Команды оболочки вроде lsбудут получать предупреждения в стиле переполнения, потому что они не предназначены для работы с миллионами (или более) изображений. Как я могу управлять таким огромным количеством файлов? Если, например, я хочу найти изображение посередине (в соответствии с меткой времени в имени и времени создания), существует ли какая-либо файловая система, которая предлагает встроенную функцию поиска? Какие команды вы бы использовали? Я попробовал удобный lsиfindс необходимыми флагами, но они были либо очень медленными, либо генерировали предупреждения, поэтому я думаю, что либо мне нужна лучшая файловая система, либо db, либо что-то подобное для предварительного индексирования изображений. Мне в основном нужен один массив, в который иноды фотографий должны быть расположены в хронологическом порядке. Как это сделать? Позже могут быть добавлены метаданные с метками времени Unix.

[Обновить]

В текущих ответах есть серьезный недостаток, люди просто публикуют некие эмпирические тесты. Если бы они проверили свои предложения, они, вероятно, потерпели бы неудачу. Поэтому я создал для вас инструмент командной строки, с помощью которого вы можете создать «песочницу» для создания огромного количества файлов и проверить свои предложения, например, с количеством файлов 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 для наборов данных в этом масштабе, правильная индексированная база данных, вероятно, единственный вариант
xenoterracide
@xenoterracide: но даже dbs должен реализовывать быстрый поиск с чем-то вроде массивов, db звучит излишне. Источник для фотосъемки здесь: github.com/fsphil/fswebcam . Возможно, я мог бы немного изменить его, чтобы сохранить изображение, чтобы добавить строку с номером inode-номера и меткой времени unix в файл. Теперь не с картинками, а с линией, поиск картинок будет намного быстрее. Или еще проще: каждый раз, когда изображение сохраняется на диске, я добавляю строку в файл с его отметкой времени. Круглое решение. Но не решит проблему с текущими фотографиями, поэтому вопрос актуален.
@hhh какую файловую систему вы используете? или это не имеет значения ... Ext имеет некоторые функции повышения производительности, которые могут быть не включены по умолчанию. Хотя даже те, которые, вероятно, не будут иметь дело с масштабом, о котором вы говорите. БД оптимизированы для этих целей и имеют различные решения по индексированию для их решения. например, индекс btree - это не просто массив ...
xenoterracide
@xenoterracide: ext3, не уверен, имеет ли это значение. Я думаю, что решение, которое я иллюстрировал, решает проблему для будущей проблемы поиска, но это не помогает с текущими фотографиями, это занимает очень много времени, чтобы искать его.
1
У вас есть миллионы файлов в одном каталоге? Если это так, вы можете подумать о разделении их на глубокие поддиректории одного или двух уровней, основанные на первых символах имени файла, например:a/b/abcdef.jpg
alex

Ответы:

4

Попробуйте другую оболочку. Я бы порекомендовал попробовать zsh, например, и посмотреть, позволяет ли он больше параметров.

Если я правильно понимаю, часть имени файла - это метка времени UNIX. Может быть целесообразно разделить файлы на папки. Если формат даты / времени представляет собой число эпох UNIX, поместите куски фракций этого числа, скажем, 10000, в отдельную папку.

Если временная метка ISO 8601 является частью имени файла, просто разделите на год, месяц или день.

Полемон
источник
1
ls и find не являются встроенными в bash или zsh, поэтому неясно, как переключение оболочек поможет в этом случае.
Робин Грин
Речь идет о расширении оболочки. Если оболочка не может расширить глобализацию, это может быть проблемой.
Полемон
Я сделал несколько тестов , выполнение команд на около 1E6 файлов, ЗШ сталкивается с теми же проблемами: "$ 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) чем-нибудь вам помочь?

asoundmove
источник
1
updatedbиспользует find.
dave1010
@ dave1010, конечно, но время от времени это происходит в фоновом режиме, поэтому, если для OP приемлемо, что он не обязательно обновляется каждую минуту, но, возможно, один раз в день, тогда график обновляется b в тихий час (или расписание обновляется часто, но с низким приоритетом (что и должно быть в любом случае), а затем с помощью команды locate очень быстро найти то, что вы хотите. Поэтому ключевой вопрос заключается в том, насколько актуальной должна быть БД (или индекс для любой другой такой системы).
asoundmove