Извлечение файлов .gz, содержащихся в папке

13

У меня есть папка, содержащая приблизительно 320116 файлов .pdb.gz. Я хочу распаковать их всех. Если я использую gunzip * .gz, это выдает ошибку, т.е. список аргументов слишком длинный. Папка составляет около 2 ГБ. Пожалуйста, дайте мне соответствующее предложение.

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

Ответы:

26
find . -name '*.pdb.gz' -exec gunzip {} +

-exec gunzip {} +предоставит gunzipмного, но не слишком много имен файлов в командной строке. Это более эффективно, чем -exec gunzip {} \;запуск нового gunzipпроцесса для каждого файла.

John1024
источник
3
Один find, меньше gunzip!
Дан
2
Обратите внимание, что «+» является GNUism и поэтому не будет работать в не-GNU системах, таких как * BSD.
Восстановить Монику - М. Шредер
3
Более поздние версии BSD findдопускают нотацию «+». Смотрите, например, на findстранице руководства BSD 10.1 . Также относится к OS X (10.9 и позже, по крайней мере, может быть, раньше).
плазма
7

Всякий раз, когда вы получаете ошибки «список аргументов слишком длинный», вы можете обойти это, вызвав нужную команду несколько раз, каждый раз с подмножеством аргументов, которые вы хотите использовать. xargsэто инструмент, который поможет вам сделать это автоматически.

find . -type f -a -name \*.pdb.gz -print0 | xargs -0 gunzip
Celada
источник
разве это не имеет такой же неэффективности, как -execdir gunzip "{}" \;то есть то, что xargs будет вызывать gunzip отдельно для каждого файла? Это мое чтение страницы руководства.
gogoud
5
Нет, xargsзаполнит столько имен файлов, сколько поместится в gunzipкомандной строке. Попытайся! echo a b c d e f | xargs echoвызывается только echoодин раз со всеми 6 аргументами, так что вы видите одну строку вывода (довольно бесполезная команда для выполнения, хотя !!!!), в то время как если вы заставляете xargsуказывать только 3 аргумента за вызов команды, используя, echo a b c d e f | xargs -n 3 echoто вы получите 2 строки вывода ,
Селада
4
Еще одним преимуществом использования xargsявляется то, что с помощью этой -Pопции вы можете запускать несколько gunzipпроцессов параллельно, что (в зависимости от точных параметров вашей системы) может идти быстрее.
psmears
спасибо за указатель на -P@psmears. Теперь я тоже кое-что узнал!
Селада
1

Я думаю, что это должно работать, он передает путь / имя каждого файла в gunzip для обработки:

find /my/dir -name "*.pdb.gz" -execdir gunzip "{}" \;
gogoud
источник
1
Это выполнит gunzip один раз за файл. См . Ответ Джона 1024 о том, как избежать этой неэффективности.
Селада
@Celada Это было преднамеренно; Меня беспокоило, что использование + может снова привести к сообщению об ошибке из-за перегрузки gunzip. Если метод Джона 1024 работает, он технически более эффективен, но мой должен работать, если его нет.
gogoud
1
findс +и xargsявно дизайнер с именно этой проблемой в виду. Они всегда будут указывать столько аргументов, сколько смогут, не превышая ограничения операционной системы. Потому что, кстати, он является ценз работы системы, ничего общего с gunzip.
Селада
1
@Celada хорошо, спасибо за эту информацию, так что, предположительно, с '+' gunzip может быть вызван более одного раза, но менее 320 000 раз?
gogoud
1
верный.
Селада
1

Попробуйте так:

find . -name '*.gz' -exec gunzip {} \;
jherran
источник
3
Это будет выполняться gunzipодин раз для каждого файла. См . Ответ Джона 1024 о том, как избежать этой неэффективности.
Селада
Обязательно избегайте * in * .gz ...
user253751
1

Если у вас многоядерный компьютер, вы, вероятно, увидите, что его использование gunzipне позволит максимально использовать возможности вашего компьютера. Для этого вам нужно будет запустить несколько gunzips параллельно. Следить за тем, что сделано, в каком терминале вручную, является громоздким, но вы можете легко сделать это с помощью параллельной GNU:

find . -name "*.gz" | parallel -X gunzip {}
Энтон
источник
1
Разве это не сработает, потому что список аргументов parallelслишком длинный?
user253751
@immibis Да, я забыл исходную проблему, я обновлю свой пост
Anthon
Не будет ли еще терпеть неудачу , потому что список аргументов , чтобы findслишком долго?
user253751
1
да, но вы передаете все имена файлов в findкомандной строке.
user253751
Кажется, это не хороший день, чтобы отвечать на вопросы, я забыл процитировать этот аргумент-name
Anthon
-1

findНет необходимости использовать для этого, так как вы не упомянули подпапки. Что вам нужно сделать, это:

for f in *.gz;do gunzip $f;done
Толга Озсес
источник
4
Вы действительно нужно , findесли вы не хотите , чтобы породить 320116 gunzipпроцессы, так же , как этот цикл делает.
Джон У. С. Смит,