2010-04-23 3 views
21

Я получил работу, работающую на моем сервере в командной строке в течение двух дней в настоящее время:Более эффективный способ найти и очернить миллионы файлов

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

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

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

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

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

+6

ехес параметр порождает новый процесс дегтя для каждого найденного файла. Кроме того, операция обновления tar дорогая. – theomega

+0

сколько у вас файлов и насколько они велики? влияние вызова tar для каждого из файлов имеет большое значение для 10 файлов с петабайтом или 10 миллиардов небольших файлов. – sfussenegger

+0

@sfussenegger: по 8 байт ... обновлен вопрос. Как указано в q, есть * миллионы * файлов. –

ответ

19

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

+0

После запуска с помощью 'xargs' некоторое время я пробовал этот подход ... и это было ** намного ** быстрее! –

+2

будьте осторожны с 'xargs' в этой ситуации: если к нему передано много имен файлов, он несколько раз выполняет« tar »в подмножествах списка файлов. В вашем случае с «tar -u», который, вероятно, работает, но если вы создаете tar-файл «tar -c», только последний подмножество файлов будет там, как только он будет закончен ... – drevicko

7

Существует xargs для этого:

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

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

+0

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

+0

Думаю, вам нужно будет добавить '--max-args = n' (short' -n n'), где 'n' - максимальное количество аргументов tar (или любой другой программы). 'getconf ARG_MAX' должен показать, насколько высок этот предел (131 072 на моей машине). Возможно, что xargs позаботится об этом. – sfussenegger

+0

Ничего себе! Поэтому я запустил еще одну команду с 'xargs', как вы сказали 15 минут назад, а полученный tar-файл уже составляет 25% от размера моей исходной команды. Благодарю. –

2

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

24

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

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

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

+2

Это элегантное решение. и вы можете запускать его по сети. замените '> 2009.tar' на' | ssh host tar xf -' – 2011-03-11 22:05:32

+5

'найти данные/-print0 | tar -T - --null --create -f archive.tar' считывает список файлов из stdout и использует ограничитель нулевого файла –

+3

. Мой ubuntu tar не любит иметь '--null' после' -T'. Мне пришлось использовать: 'найти данные/-print0 | tar --null -T - --create -f archive.tar' –

8

Вот находка-тары комбинация, которая может делать то, что вы хотите без использования 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 - 
3

Чтобы правильно обрабатывать имена файлов со странными (но законными) символами (такими как новые строки, ...), вы должны написать свой список файлов в файлыOfInterest.TXT, используя -print0 ФАЙНД:

find -x data -name "filepattern-*2009*" -print0 > filesOfInterest.txt 
tar --null --no-recursion -uf 2009.tar --files-from filesOfInterest.txt 
-2

Простейшим (и удалить файл после создания архива):

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

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

Смежные вопросы