2013-05-27 3 views
4

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

tar czf my_app.tar.gz 

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

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

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

+1

Как насчет того, чтобы циклическое добавление 'app_item' к переменной и, наконец, выполнение' tar $ that_variable'? – fedorqui

+0

Какая ошибка вы получаете? –

+0

Спасибо @fedorqui, ваше обходное решение делает трюк! – alexs333

ответ

5

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

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

Подробнее об этом объясните the page he linked to.

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

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

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

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

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

+2

Или, скорее, один «tar rf my_app.tar» $ {app_items [@]} ", если массив не гигантский. – l0b0

+0

Конечно. Я думаю, что вся идея итерации возникла из-за того, что вы не могли использовать один лайнер, который вы дали. (Но, возможно, OP просто не думал об этом.) – Alfe

+1

'tar: Трусливый отказ от создания пустого архива' - решен путем изменения первой строки на' tar cf my_app.tar -files-from/dev/null' (из [здесь] (http://www.wezm.net/technical/2008/03/create-empty-tar-file/)) – Matthias

1

Сделайте файл с именами в массиве, а затем используйте параметр -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$$ 
Смежные вопросы