I have an array with files and directories that I wish to add to the compressed tar (tar.gz). Originally I was planning to loop through the array and add each item to the tar, something like that:
tar czf my_app.tar.gz
for app_item in "${app_items[@]}"
do
tar rzf my_app.tar.gz $app_item
done
Running the script I have found that I cannot add files to the compressed tar. I was wondering whether there is any other way of creating a tar from my list of location in the array.
Any help would be greatly appreciated!
The problem only exists with compressed archives. I propose to create and use an uncompressed archive first and compress it later when the loop has been run through.
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
As @Matthias pointed out in a comment, creating an empty archive (what we want in the first line) is typically refused by tar
. To force it to do this, we need a trick which differs from operating system to operating system:
tar cf empty.tar --from-file /dev/null
tar cvf empty.tar --files-from /dev/null
tar cvf empty.tar -I /dev/null
More details about this explains the page he linked to.
A completely different approach which also seems to work nicely with file names with spaces in them (but not with file names with newlines in them, so it is not quite as general):
tar cfz my_app.tgz --files-from <(printf "%s\n" "${app_items[@]}")
And yet another way of doing this (which also works with newlines and other stuff in the file names):
eval tar cfz my_app.tgz $(printf "%q " "${app_items[@]}")
But as usual with eval
you should know what you pass to it and that nothing of this comes from an untrusted source, otherwise it might pose a security issue, so in general I recommend to avoid it.
Make a file with the names in the array, and then use the -T
option of tar (BSD or GNU) to read that file. This will work for any number of files, will work with files with spaces in the names, and will compress while archiving to minimize required disk space. E.g.:
for (( i = 0; i < ${#app_items[@]}; i++))
do
echo ${app_items[$i]} >> items$$
done
tar cfz my_app.tar.gz -T items$$
rm items$$
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With