This question is from a while ago, but I still could not find the answer for myself easily for adding files and folders with specific search criteria with relative paths.
The following covers a broader topic than what has been asked. So, I am writing up the solution I came up following my research.
Let's assume your $input_dir
variable points to your directory of interest and you are looking to tar and compress (using gzip) all your *.txt
files into ~/my_txt.tar.gz
. To create a gzipped tarball with no path stored in the tar (relative path), use the following:
find "$input_dir" -maxdepth 1 -type f -name "*.txt" -printf "%P\0" | tar --null --create --remove-files --gzip --file="$HOME/my_txt.tar.gz" --directory="$input_dir" --files-from=-
Let's break it down:
"$input_dir"
: The starting-point directory. Change it to whatever you like.
maxdepth 1
: only looks in the root of that directory. You can remove or modify it if you want to search all or different levels.
-type f
: search only for files
-name "*.txt"
: matching the *.txt criteria
-printf "%P"
: output the Relative Path (man page: "File's name with the name of the starting-point under which it was found removed").
-printf "%P\0"
: null terminate the relative path outputs
| tar
: pipe the outputs to the next command which is tar here
--null
: instructs subsequent --files-from
option to read null-terminated names. Remember that we asked find
to create null terminated (\0
) outputs instead of regular \n
terminated outputs. This is to cover all possible filenames with spaces or other special characters.
--create
: create the tar file. Equal to -c
.
--remove-files
: I use this option to remove the files after they are added to the tarball. You can drop it.
--gzip
: gzip the tarball. Equal to -z
.
--file="$HOME/my_txt.tar.gz"
: The output gzipped tarball file. Equal to -f "$HOME/my_txt.tar.gz"
--directory="$input_dir"
: This means that tar
now changes to this directory. Now it will look for the filenames that is passed on in this directory (remember that we have made the filenames' relative path to this folder). Equal to -C "$input_dir"
.
--files-from=/dev/stdin
: Its general form is --files-from=FILE
. This option with the --null
option instructs tar
that the names in FILE
are separated by ASCII NULL character, instead of the Line Feed (\n
). We also say that the FILE
is stdin
(piped from find
directly to tar
rather than reading from a FILE
on disk). Equal to -T -
.
Some of the above can be changed to one character options and can be combined.
find "$input_dir" -maxdepth 1 -type f -name "*.txt" -printf "%P\0" | tar --null --remove-files -czf "$HOME/my_txt.tar.gz" -C "$input_dir" -T -
You can check the file list using -t
or --list
option:
tar -tf "$HOME/my_txt.tar.gz"
Now to extract the files to $output_dir directory (which exists), use this:
tar -xvzf "$HOME/my_txt.tar.gz" -C "$output_dir"
The v
option is verbose and you can also add it during tarball creation.