Bash - создание tar для элементов массива

У меня есть массив с файлами и каталогами, которые я хочу добавить в сжатый tar (tar.gz). Первоначально я планировал цикл через массив и добавлял каждый элемент в tar, что-то вроде этого:

tar czf my_app.tar.gz
for app_item in "${app_items[@]}"
do
 tar rzf my_app.tar.gz $app_item
done

Запуск script Я обнаружил, что я не могу добавить файлы в сжатый tar. Мне было интересно, есть ли другой способ создания tar из моего списка местоположений в массиве.

Любая помощь будет принята с благодарностью!

2 ответа

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

tar cf my_app.tar --files-from /dev/null
for app_item in "${app_items[@]}"
do
 tar rf my_app.tar "$app_item"
done
gzip my_app.tar

Как отметил @Matthias в комментарии, создание пустого архива (что нам нужно в первой строке) обычно отклоняется tar. Чтобы заставить это сделать, нам нужен трюк, который отличается от операционной системы до операционной системы:

  • BSD: tar cf empty.tar --from-file /dev/null
  • GNU (Linux): tar cvf empty.tar --files-from /dev/null
  • Solaris: tar cvf empty.tar -I /dev/null

Подробнее об этом объясняется страница, с которой он связан.

Совсем другой подход, который также хорошо работает с именами файлов с пробелами в них (но не с именами файлов с новыми символами в них, поэтому он не совсем как общий):

tar cfz my_app.tgz --files-from <(printf "%s\n" "${app_items[@]}")

И еще один способ сделать это (который также работает с новыми символами и другими файлами в именах файлов:

eval tar cfz my_app.tgz $(printf "%q " "${app_items[@]}")

Но, как обычно, с eval вы должны знать, что вы передаете ему, и что ничего из этого не происходит из ненадежного источника, иначе это может вызвать проблему безопасности, поэтому я рекомендую вообще избегать этого.


Создайте файл с именами в массиве, а затем используйте параметр -T для tar (BSD или GNU) для чтения этого файла. Это будет работать для любого количества файлов, будет работать с файлами с пробелами в именах и будет сжиматься при архивировании, чтобы свести к минимуму требуемое дисковое пространство. Например:.

for (( i = 0; i < ${#app_items[@]}; i++))
do
 echo ${app_items[$i]} >> items$$
done
tar cfz my_app.tar.gz -T items$$
rm items$$

licensed under cc by-sa 3.0 with attribution.