4

У меня есть большая папка с архивами RAR. Существует значительная иерархия уровней папок. Я хочу разархивировать всю коллекцию архивов одновременно.

У меня есть следующий однострочник, который будет работать:

find -name "*.rar" -print0 | xargs -0 -n 1 -P 4 unrar x

(Обратите внимание, что мы запускаем четыре потока параллельно, чтобы ускорить работу. :-))

Проблема с этой командой заключается в том, что xargs выполняется в каталоге верхнего уровня для каждого файла RAR. Это означает, что весь вывод выводится в папку верхнего уровня.

Вместо этого я хочу, чтобы выходные данные существовали в той же папке, что и архив RAR.

Пример:

Top level
 |--FolderA
 |----File1.rar
 |----File2.rar
 |--FolderB
 |----File1.rar
 |----File2.rar
 |----File3.rar
 |--FolderC
 |----File1.rar
 |----File2.rar

Каждый из файлов «File1.rar» содержит файл с таким же именем. Таким образом, извлечение их всех в папку верхнего уровня вызывает проблемы с перезаписью.

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

Мне кажется, что решение состоит в том, чтобы как-то установить рабочий каталог, а затем запустить там форму команды unrar. Однако, так как команда find дает мне имена файлов, а не каталоги, я не могу сделать что-то вроде

| xargs -I{} -n 1 -P 4 cd {} \; unrar x {}

Если не считать написания сценариев Perl или Python, которые будут обтекать команду unrar и обрабатывать разбиение предоставленного пути на его части и выполнение команды, есть ли лучший способ добиться этого?

3 ответа3

3

Существуют команды для извлечения имени каталога (dirname) и имени файла (basename) из пути. Так что вы могли бы сделать что-то вроде

find . -name '*.rar' -print0 | \
xargs -0 -I{} -n1 -P4 /bin/sh -c 'cd "$(dirname {})"; unrar x "$(basename {})"'

AFAIK , xargs не поддерживает смену каталогов, поэтому для этого вам понадобится посредник, следовательно, /bin/sh . Вы упомянули, что пишете обёртку вокруг unrar , и это в основном то, что он делает, за исключением однострочной формы.

1

Используя GNU Parallel это выглядит так:

find . -name '*.rar' | parallel cd {//} '&&' unrar x {/}

GNU Parallel - это общий параллелизатор, который позволяет легко запускать задания параллельно на одной и той же машине или на нескольких машинах, к которым у вас есть доступ по ssh.

Если у вас есть 32 различных задания, которые вы хотите запустить на 4 процессорах, прямой способ распараллеливания - запустить 8 заданий на каждом процессоре:

Простое планирование

GNU Parallel вместо этого порождает новый процесс после его завершения - поддерживая процессоры активными и, таким образом, экономя время:

Параллельное планирование GNU

Монтаж

Если GNU Parallel не упакован для вашего дистрибутива, вы можете выполнить личную установку, которая не требует root-доступа. Это можно сделать за 10 секунд, выполнив это:

(wget -O - pi.dk/3 || curl pi.dk/3/ || fetch -o - http://pi.dk/3) | bash

Для других вариантов установки см. Http://git.savannah.gnu.org/cgit/parallel.git/tree/README.

Учить больше

Смотрите больше примеров: http://www.gnu.org/software/parallel/man.html

Посмотрите вступительные видеоролики: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

Просмотрите учебник: http://www.gnu.org/software/parallel/parallel_tutorial.html

Подпишитесь на список рассылки, чтобы получить поддержку: https://lists.gnu.org/mailman/listinfo/parallel

0

Если вам не нужна опция -P xargs , то вы можете использовать опцию find -execdir , которая похожа на -exec но перед выполнением делает cd в каталог. Пример по адресу: https://stackoverflow.com/questions/16541582/finding-multiple-files-recursively-and-renaming-in-linux/54163971#54163971

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .