Распаковка нескольких файлов одновременно

27

У меня есть более 200 .zipфайлов в одной папке. Я не хочу распаковывать их по одному. Я хочу извлечь те, которые используют одну команду или скрипт. Как это сделать.

G_p
источник

Ответы:

38

Если вы действительно хотите распаковать их параллельно, вы можете сделать

for i in *zip; do unzip "$i" & done

Это, однако, запустит N процессов для N .zip файлов и может быть очень тяжелым в вашей системе. Для более контролируемого подхода, запускающего только 10 параллельных процессов одновременно, попробуйте следующее:

find . -name '*.zip' -print0 | xargs -0 -I {} -P 10 unzip {}

Чтобы контролировать количество запущенных параллельных процессов, измените -Pна что хотите. Если вы не хотите переходить в подкаталоги, сделайте это:

find . -maxdepth 1 -name '*.zip' -print0 | xargs -0 -I {} -P 10 unzip {}

Кроме того, вы можете установить GNU параллельно, как предложено @OleTange в комментариях, и запустить

parallel unzip ::: *zip
terdon
источник
3
Параллельная работа - хорошая идея, но разве дисковый ввод-вывод не будет основным узким местом?
Пэдди Ландау
1
@PaddyLandau не уверен, я должен проверить. Это будет зависеть от скорости алгоритма распаковки от скорости диска, который я себе представляю.
Тердон
Используйте -execили -execdirвместо того, чтобы обвязать xargs. Это не только проще для понимания, но и менее подвержено ошибкам и использует меньше системных ресурсов. find . -name '*.zip' -exec unzip {} ';'(Вы должны цитировать точку с запятой.)
Пэдди Ландау
@PaddyLandau единственная причина, по которой я пишу xargs, - это запускать вещи параллельно, как просил OP. -exec \;(вы можете избежать точки с запятой, без кавычек), будет запускать каждую команду последовательно. -exec +лучше, но это не сработает, потому что это не так unzip.
Тердон
Я думаю, что мы поняли ОП по-другому. Вы читаете его как желающего параллельно, тогда как я понимал его как означающий одну команду вместо нескольких команд. Ну, у него есть оба метода сейчас :)
Пэдди Ландау
17

GNU параллельно команда хорошо подходит для такого рода вещи. После:

$ sudo apt-get install parallel

затем

ls *.zip | parallel unzip

При этом будет использовано столько ядер, сколько у вас есть, и каждое ядро ​​будет разархивировано, пока все они не будут готовы.

Уэйн Конрад
источник
Лучше использовать echo *.zipвместо этого, чтобы предотвратить возможное проникновение псевдонима ls в дополнительную информацию. Однако это та же проблема, что и в ответе @ Guru, это касается имен файлов, содержащих пробелы.
nyuszika7h
1
@ nyuszika7h В отличие от xargsGNU Parallel не разбивается на имена файлов, содержащие пробел / tab / quote. Только если имена файлов содержат символы новой строки, вам придется проявлять особую осторожность. Например, используя:parallel unzip ::: *.zip
Ole Tange
@ nyuszika7h - это веские причины избегать как псевдонимов стандартных команд, так и вставки пробелов в именах файлов.
Уэйн Конрад
@ nyuszika7h использование echoтак же плохо, как использование ls. Globbing и цикл времени - самый безопасный.
тердон
1
@NateEldredge Хотя этот шанс был больше в то время, когда в системах был только один магнитный диск, в наши дни с RAID-массивами с несколькими шпинделями и флэш-диском этот шанс меньше. Лучше всего, конечно, измерить и посмотреть, как ведет себя ваша система. Недавно я использовал RAID с 40 шпинделями, где оптимальный параллелизм для процессов, требующих ввода-вывода, составлял 10: он не давал ускорения в 10 раз - только в 6 раз, но менее чем в 10 процессах - менее чем в 6 раз.
Оле Танге
12

Вы можете использовать следующую команду:

Сначала измените каталог в терминале на каталог, содержащий файлы .zip:

cd /path

Затем выполните эту команду, чтобы разархивировать все файлы .zip:

for z in *.zip; do unzip "$z"; done
Nux
источник
10

Если .zipв вашей папке много файлов и вы хотите распаковать их все, откройте терминал и перейдите в вашу папку, используя:

cd <path_to_folder>

Теперь используйте эту команду, чтобы распаковать весь ваш .zipфайл:

ls *.zip | xargs -n1 unzip
G_p
источник
3
Это не удастся, если любое из имен файлов будет содержать пробелы.
Terdon
1
да вы правы.
g_p
echo *.zipВместо этого лучше использовать эту возможность, чтобы предотвратить возможное lsпроникновение псевдонима в дополнительную информацию, однако это по-прежнему не устраняет проблему пробелов.
nyuszika7h
1
@OleTange Если вы не заметили, я сказал, что он по-прежнему не работает на именах файлов с пробелами в них.
nyuszika7h
1
Никогда не зависите от выходных данных lsдля скриптов for, так как их выходные данные не определены между версиями. Вместо этого посмотрите на ответ @terdon, поскольку он решает все проблемы этого решения.
Пэдди Ландау
6

Вы можете использовать найти -execкак так,

find . -name "*.zip" -exec unzip {} \;

Это будет работать, если в имени файла есть пробел.

Эллиот Фриш
источник
3

Нетерминальный метод.

Просто выберите zip-файлы, щелкните правой кнопкой мыши и выберите extract here. Вы можете выбрать все или только несколько zip-файлов одновременно.

Parto
источник
1

unzip \*.zip или unzip '*.zip'

Очевидное unzip *.zipне работает, потому что оболочка расширяет его unzip foo.zip bar.zip ...и unzipинтерпретирует первое имя файла как zip-файл, а следующие имена файлов как файлы для извлечения из этого zip-файла.

Тем не менее, unzipэто немного необычно для команд Unix в том смысле, что он делает свои собственные расширения глобуса. Если *оболочка не раскрывается, unzip сделает это и интерпретирует все полученные имена файлов как zip-файлы для обработки. Так что в этом особом случае можно обойтись без forпетли xargsили чего-то подобного.

Нейт Элдридж
источник