Более эффективный способ поиска и архивирования миллионов файлов - PullRequest
21 голосов
/ 23 апреля 2010

В течение двух дней на моем сервере запущено задание в командной строке:

find data/ -name filepattern-*2009* -exec tar uf 2009.tar {} ;

Требуется навсегда , а затем и немного. Да, в целевом каталоге находятся миллионы файлов. (Каждый файл занимает всего 8 байтов в хорошо хэшированной структуре каталогов.) Но просто работает ...

find data/ -name filepattern-*2009* -print > filesOfInterest.txt

... занимает всего два часа или около того. При том, что моя работа выполняется, она не будет закончена в течение пары недель .. Это кажется неразумным. Есть ли более эффективный способ сделать это? Может быть, с более сложным сценарием bash?

Второстепенный вопрос «Почему мой нынешний подход такой медленный?»

Ответы [ 8 ]

24 голосов
/ 23 апреля 2010

Один из вариантов - использовать cpio для создания архива в формате tar:

$ find data/ -name "filepattern-*2009*" | cpio -ov --format=ustar > 2009.tar

cpio изначально работает со списком имен файлов из stdin, а не с каталогом верхнего уровня, что делает его идеальным инструментом в этой ситуации.

19 голосов
/ 23 апреля 2010

Если вы уже выполнили вторую команду, которая создала список файлов, просто используйте опцию -T, чтобы указать tar прочитать имена файлов из этого списка сохраненных файлов. Выполнение 1 команды tar по сравнению с N командами tar будет намного лучше.

8 голосов
/ 23 апреля 2010

Вот комбинация find-tar, которая может делать то, что вы хотите без использования xargs или exec (что должно привести к заметному ускорению):

tar --version    # tar (GNU tar) 1.14 

# FreeBSD find (on Mac OS X)
find -x data -name "filepattern-*2009*" -print0 | tar --null --no-recursion -uf 2009.tar --files-from -

# for GNU find use -xdev instead of -x
gfind data -xdev -name "filepattern-*2009*" -print0 | tar --null --no-recursion -uf 2009.tar --files-from -

# added: set permissions via tar
find -x data -name "filepattern-*2009*" -print0 | \
    tar --null --no-recursion --owner=... --group=... --mode=... -uf 2009.tar --files-from -
7 голосов
/ 23 апреля 2010

Для этого есть xargs:

find data/ -name filepattern-*2009* -print0 | xargs -0 tar uf 2009.tar

Гадать, почему это медленно, сложно, так как информации не так много. Какова структура каталога, какую файловую систему вы используете, как она была настроена при создании. Наличие миллионов файлов в одном каталоге - довольно сложная ситуация для большинства файловых систем.

3 голосов
/ 01 мая 2010

Чтобы правильно обрабатывать имена файлов со странными (но допустимыми) символами (например, символами новой строки, ...), вы должны записать свой список файлов в filesOfInterest.txt, используя find's -print0:

find -x data -name "filepattern-*2009*" -print0 > filesOfInterest.txt
tar --null --no-recursion -uf 2009.tar --files-from filesOfInterest.txt 
2 голосов
/ 23 апреля 2010

То, как у вас сейчас есть вещи, вы вызываете команду tar каждый раз, когда она находит файл, что неудивительно медленно.Вместо того, чтобы потратить два часа на печать плюс количество времени, которое требуется, чтобы открыть архив tar, посмотреть, устарели ли файлы, и добавить их в архив, вы фактически умножаете эти времена вместе.Возможно, вы добьетесь большего успеха, вызвав команду tar один раз, после объединения всех имен, возможно, используя xargs для выполнения вызова.Кстати, я надеюсь, что вы используете 'filepattern- *2009*', а не filepattern- *2009*, так как звезды будут расширяться оболочкой без кавычек.

1 голос
/ 20 ноября 2018

Для этого есть утилита под названием tarsplitter.

tarsplitter -m archive -i folder/*.json -o archive.tar -p 8

будет использовать 8 потоков для архивирования файлов, соответствующих "folder / *. Json", в выходной архив "archive.tar"

https://github.com/AQUAOSOTech/tarsplitter

0 голосов
/ 14 июля 2013

Самый простой (также удалить файл после создания архива):

find *.1  -exec tar czf '{}.tgz' '{}' --remove-files \;
...