Что здесь происходит?
Изначально команда tar
предназначалась для использования с устройствами на магнитной ленте. Поскольку имеет смысл выполнять tar
только на одном устройстве за раз, синтаксис был разработан для использования одного и только одного устройства. Предполагалось, что первым переданным файлом или каталогом будет устройство, в котором находится рассматриваемый архив, и любые другие файлы или каталоги, в которых содержимое архива будет включено в операцию. Таким образом, для извлечения tar
(опция x
) первым переданным файлом будет архив, а все остальные файлы будут файлами, которые будут извлечены. Таким образом, если есть два *.tar
файла (скажем, a.tar
и b.tar
), ваша команда расширится до:
$ tar xf a.tar b.tar
Если a.tar
не содержит файл с именем b.tar
, команда tar
не имеет ничего общего и тихо завершает работу. Досадно, что версия Solaris tar
не сообщает о каких-либо проблемах ни с кодом возврата, ни с подробной опцией (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
loop:
$ 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
содержат один и тот же файл и пытаются извлечь его одновременно, результаты непредсказуемы.
Связанная проблема, особенно при получении архивов из ненадежного источника, заключается в возможности тарбомбы .
Одним из частичных решений было бы автоматическое создание нового каталога для извлечения в:
for f in *.tar; do
d=`basename "$f" .tar`
mkdir "$d"
(cd "$d" && tar xf "../$f")
done
Это не поможет, если файл указан в архиве с абсолютным путем (что обычно является признаком злонамеренного намерения). Добавление такого рода проверки оставлено читателю в качестве упражнения.