Bash - creating tar for array elements

I have an array with files and directories that I want to add to compressed tar ( tar.gz ). I originally planned a loop through an array and added each element to tar, something like this:

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 found that I cannot add files to the compressed tar. I was wondering if there is another way to create tar from my list of locations in the array.

Any help would be greatly appreciated!

+4
source share
2 answers

The problem exists only with compressed archives. I suggest first creating and using an uncompressed archive and compressing it later when the cycle has passed.

 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 noted in a comment, creating an empty archive (what we need in the first line) is usually rejected by tar . To get this done, we need a trick that differs from the operating system to the operating system:

  • 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

This is explained in more detail on the page with which it is associated .

A completely different approach, which also works well with file names with spaces in them (but not with file names with new characters in them, so it’s not quite as general):

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

And another way to do this (which also works with new characters and other files in file names:

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

But, as usual, with eval you should know what you pass it to it and that none of this comes from an untrusted source, otherwise it can cause a security problem, so I recommend that you avoid this at all.

+5
source

Create a file with the names in the array, and then use the -T option to tar (BSD or GNU) to read this file. This will work for any number of files, will work with files with spaces in the names and will be compressed during archiving to minimize the required disk space. For instance:.

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

Source: https://habr.com/ru/post/1482916/


All Articles