Как можно распаковать более одного файла за раз?

У меня есть куча tar файлов в каталоге, и я хочу извлечь из них все файлы сразу. Но, похоже, это ничего не дает:

$ tar xf *.tar

Что тут происходит? Как распаковать сразу несколько файлов?

Ответов (3)

find . -maxdepth 1 -name '*.tar' -exec tar -xf '{}' \;

Если все файлы tar находятся в одной папке, я делаю это в оболочке tcsh. Работает постоянно.

find -iname \*.tar -exec tar -xvf {} \;

Это то же самое, что и ответ выше, я думаю, немного более сжатый.

Что тут происходит?

Изначально 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 даже при отключенной опции подробного вывода:

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

Это не поможет, если файл указан в архиве с абсолютным путем (что обычно является признаком злого умысла). Добавление такого рода проверки оставлено в качестве упражнения для читателя.