Linux – Tar a List of Files Without Their Directory Structure

centoslinuxtar

Say I do this:

tar cvf allfiles.tar $(<mylist.txt)

and mylist.txt contains this:

/tmp/lib1
/tmp/path2/lib2
/path3/lib3

How to tar the files so the tarball contains just

lib1
lib2
lib3

with no directory structure at all?


The -C of --directory options are usually recommended (ref, ref), but there are multiple directories so this doesn't work. Also, --xform looks like it requires a fixed pattern (ref) which we do not have.

Best Answer

The --xform argument takes any number of sed substitute expressions, which are very powerful. In your case use a pattern that matches everything until the last / and replace it with nothing:

tar cvf allfiles.tar --xform='s|.*/||' $(<mylist.txt)

Add --show-transformed-names to see the new names.

Note, this substitution applies to all filenames, not just those given on the command line, so, for example, if you have a file /a/b/c and your list just specifies /a, then the final filename is just c, not b/c. You can always be more explicit and provide an exact list of substitutions, eg in your case

--xform='s|^tmp/path2/||;s|^tmp/||;s|^path3/||'

Note, the initial / will be removed by tar (unless you use -P) so the above expressions are missing it. Also, the list of directories has to be sorted so the longest match is done first, else tmp/path2/ won't match as tmp/ has already been removed. But you can automate the creation of this list, eg:

--xform="$(sed <mylist.txt 's|[^/]*$||; s|^/||; s:.*:s|^&||;:' | sort | tr -d '\n')"