Более эффективный способ найти и смолить миллионы файлов

У меня есть задание, работающее на моем сервере при приглашении командной строки для двух дни теперь:

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

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

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

... занимает только два часа или около этого. На уровне работает мое задание, это не будет закончено в течение нескольких недель.. Это кажется неблагоразумным. Существует ли более эффективное, чтобы сделать это? Возможно, с более сложным сценарием удара?

Вопросы вторичного устройства, "почему мой текущий подход является настолько медленным?"

22
задан Stu Thompson 23 April 2010 в 09:04
поделиться

6 ответов

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

20
ответ дан 29 November 2019 в 03:43
поделиться

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

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

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

7
ответ дан 29 November 2019 в 03:43
поделиться

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

2
ответ дан 29 November 2019 в 03:43
поделиться

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

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

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

25
ответ дан 29 November 2019 в 03:43
поделиться

Вот комбинация 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 -
8
ответ дан 29 November 2019 в 03:43
поделиться

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

find -x data -name "filepattern-*2009*" -print0 > filesOfInterest.txt
tar --null --no-recursion -uf 2009.tar --files-from filesOfInterest.txt 
3
ответ дан 29 November 2019 в 03:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: