У меня есть куча файлов tar
в каталоге, и я хочу сразу извлечь все файлы из них. Но это ничего не делает:
$ tar xf *.tar
Что здесь происходит? Как разобрать кучу файлов одновременно?
У меня есть куча файлов tar
в каталоге, и я хочу сразу извлечь все файлы из них. Но это ничего не делает:
$ tar xf *.tar
Что здесь происходит? Как разобрать кучу файлов одновременно?
Первоначально команда tar
предназначалась для использования с устройствами на магнитной ленте. Поскольку было разумно выполнять tar
на одном устройстве за раз, синтаксис был разработан для использования одного и только одного устройства. Предполагалось, что первым переданным файлом или каталогом будет устройство, в котором находится рассматриваемый архив, и любые другие файлы или каталоги, в которых содержимое архива должно быть включено в операцию. Таким образом, для извлечения tar
(опция x
) первым переданным файлом будет архив, а все остальные файлы будут файлами, которые будут извлечены. Так что если есть два *.tar
файла (скажем, a.tar
и b.tar
), ваша команда расширится до:
$ tar xf a.tar b.tar
Если a.tar
содержит файл с именем b.tar
, команда tar
не имеет ничего общего и тихо завершает работу. К сожалению, версия tar
Solaris не сообщает о каких-либо проблемах ни с кодом возврата, ни с подробной опцией (v
). Тем временем GNU tar
возвращает 2
и спамит STDERR
даже при выключенной опции verbose:
tar: b.tar: Not found in archive
tar: Exiting with failure status due to previous errors
Слишком поздно переписывать tar
чтобы принять несколько архивных файлов в качестве входных данных, но это не слишком сложно, чтобы обойти ограничение.
Для большинства людей запуск tar
несколько раз для нескольких архивов является наиболее целесообразным вариантом. Передача только одного имени файла в tar xf
извлечет все заархивированные файлы, как и следовало ожидать. Одним из подходов является использование оболочки for
цикла:
$ for f in *.tar; do tar xf "$f"; done
Другой метод заключается в использовании xargs
:
$ ls *.tar | xargs -i tar xf {}
Кроме того, вы можете использовать одну из нескольких альтернативных программ чтения файлов tar
. Наконец, по-настоящему преданный программист может легко написать замену tar
которая работает именно так, как нужно. Формат прост, и многие языки программирования имеют библиотеки для чтения файлов tar
. Если вы, например, программист на Perl, взгляните на модуль Archive::Tar
.
Слепая распаковка файлов может вызвать неожиданные проблемы. Наиболее очевидным является то, что конкретное имя файла может быть включено в более чем один файл tar
. Поскольку tar
по умолчанию перезаписывает файлы, точная версия файла, с которым вы работаете, будет зависеть от порядка обработки архивов. Больше проблем, вы можете получить поврежденную копию файла, если попробуете эту "умную" оптимизацию:
for f in *.tar; do
tar xf "$f" &
done
wait
Если a.tar
и b.tar
содержат один и тот же файл и пытаются извлечь его одновременно, результаты непредсказуемы.
Связанная проблема, особенно при получении архивов из ненадежного источника, связана с возможностью создания tarbomb.
Одним из частичных решений было бы автоматическое создание нового каталога для извлечения в:
for f in *.tar; do
d='basename "$f" .tar'
mkdir "$d"
(cd "$d" && tar xf "../$f")
done
Это не поможет, если файл указан в архиве с абсолютным путем (что обычно является признаком злонамеренного намерения). Добавление такого рода проверки остается в качестве упражнения для читателя.
Если все tar файлы находятся в одной папке, я делаю это в tcsh-оболочке. Работает все время.
find -iname \*.tar -exec tar -xvf {} \;
Это то же самое, что и приведенный выше ответ, немного более сжатый, я думаю.
find . -maxdepth 1 -name '*.tar' -exec tar -xf '{}' \;