The find command used to search for files in a directory hierarchy as per given criteria. The tar command is an archiving utility for Linux, macOS, FreeBSD/OpenBSD/NetBSD and Unix-like system to create tarballs. Let us see how to combine tar command with find command to create a tarball in a single command line option.
Find command syntax
The syntax is:
find /path/to/search -name "file-to-search" -options
## find all Perl (*.pl) files ##
find $HOME -name "*.pl" -print
## find all *.doc files ##
find $HOME -name "*.doc" -print
## Safe search options for xargs or tar ##
find /path/to/dir/ -name "*.jpg" -print0
## find all *.sh (shell scripts) and run ls -l command on it ##
find . -iname "*.sh" -exec ls -l {} +
Sample outputs from the last command:
-rw-r--r-- 1 vivek vivek 1169 Apr 4 2017 ./backups/ansible/cluster/nginx.build.sh -rwxr-xr-x 1 vivek vivek 1500 Dec 6 14:36 ./bin/cloudflare.pure.url.sh lrwxrwxrwx 1 vivek vivek 13 Dec 31 2013 ./bin/cmspostupload.sh -> postupload.sh lrwxrwxrwx 1 vivek vivek 12 Dec 31 2013 ./bin/cmspreupload.sh -> preupload.sh lrwxrwxrwx 1 vivek vivek 14 Dec 31 2013 ./bin/cmssuploadimage.sh -> uploadimage.sh lrwxrwxrwx 1 vivek vivek 13 Dec 31 2013 ./bin/faqpostupload.sh -> postupload.sh lrwxrwxrwx 1 vivek vivek 12 Dec 31 2013 ./bin/faqpreupload.sh -> preupload.sh lrwxrwxrwx 1 vivek vivek 14 Dec 31 2013 ./bin/faquploadimage.sh -> uploadimage.sh -rw-r--r-- 1 vivek vivek 778 Nov 6 14:44 ./bin/mirror.sh -rwxr-xr-x 1 vivek vivek 136 Apr 25 2015 ./bin/nixcraft.com.301.sh -rwxr-xr-x 1 vivek vivek 547 Jan 30 2017 ./bin/paypal.sh -rwxr-xr-x 1 vivek vivek 531 Dec 31 2013 ./bin/postupload.sh -rwxr-xr-x 1 vivek vivek 437 Dec 31 2013 ./bin/preupload.sh -rwxr-xr-x 1 vivek vivek 1046 May 18 2017 ./bin/purge.all.cloudflare.domain.sh lrwxrwxrwx 1 vivek vivek 13 Dec 31 2013 ./bin/tipspostupload.sh -> postupload.sh lrwxrwxrwx 1 vivek vivek 12 Dec 31 2013 ./bin/tipspreupload.sh -> preupload.sh lrwxrwxrwx 1 vivek vivek 14 Dec 31 2013 ./bin/tipsuploadimage.sh -> uploadimage.sh -rwxr-xr-x 1 vivek vivek 1193 Oct 18 2013 ./bin/uploadimage.sh -rwxr-xr-x 1 vivek vivek 29 Nov 6 14:33 ./.vim/plugged/neomake/tests/fixtures/errors.sh -rwxr-xr-x 1 vivek vivek 215 Nov 6 14:33 ./.vim/plugged/neomake/tests/helpers/trap.sh
Tar command syntax
To create a tar ball of /home/vivek/projects directory, run:
$ tar -cvf /home/vivek/projects.tar /home/vivek/projects
Combining find and tar commands so that we can find and tar files into a tarball
Again the syntax is:
find /dir/to/search/ -name "*.doc" -exec tar -rvf out.tar {} \;
OR
find /dir/to/search/ -name "*.doc" -exec tar -rvf out.tar {} +
For example:
find $HOME -name "*.doc" -exec tar -rvf /tmp/all-doc-files.tar "{}" \;
## OR ##
find $HOME -name "*.doc" -exec tar -rvf /tmp/all-doc-files.tar "{}" +
Where, find command options:
- -name "*.doc" : Find file as per given pattern/criteria. In this case find all *.doc files in $HOME.
- -exec tar ... : Execute tar command on all files found by the find command.
Where, tar command options:
- -r : Append files to the end of an archive. Arguments have the same meaning as for -c option.
- -v : Verbose output.
- -f : out.tar : Append all files to out.tar file.
How to find files and tar them with special characters in file names such as white spaces
Let us see safe option to deal with file names such as:
-rw-rw-r-- 1 vivek vivek 12 Oct 28 11:38 'Hello World .sh ' -rw-rw-r-- 1 vivek vivek 18 Oct 28 11:32 'this ? *is a test.sh' -rw-rw-r-- 1 vivek vivek 18 Oct 28 11:32 'this is a test.sh'
So far we leaned how to pipe output of the find command to the tar command as follows:
find $HOME -name "*.doc" -print0 | tar -cvf /tmp/file.tar --null -T -
However, above command will fail when it see weird and special filenames. The -print0 option passed to the find command deals with special file names such as white spaces or wild characters in file names. The --null and -T - option tells the tar command to read its input from stdin or pipe. Now will use use the xargs command:
find $HOME -type f -name "*.sh" -print0 | xargs -0 tar cfvz /nfs/x230/my-shell-scripts.tgz
Where,
- -print0 : Let us print the full file name on the standard output (screen), followed by a null character (instead of the newline character that -print uses) with the find command. This allows file names that contain newlines or other types of white space to be correctly interpreted by programs that process the find output. This option corresponds to the -0 option of xargs.
- -0 or --null : Input items are terminated by a null character instead of by whitespace, and the quotes and backslash are not special (every character is taken literally). Disables the end of file string, which is treated like any other argument. Useful when input items might contain white space, quote marks, or backslashes. The GNU find -print0 option produces input suitable for this mode.
Thus, it would be best if you always used the last syntax. In other words:
find /path/ -name "file-pattern" -print0 | xargs -0 tar cfz tarball.gz
Conclusion
You learned how to search and tar files on fly safely on your Linux or Unix-like systems. See the following man pages for more info:
$ man tar
$ man find
$ man xargs
$ man bash
Also read Unix command to find a file in a directory and subdirectory.
🐧 Get the latest tutorials on Linux, Open Source & DevOps via:
- RSS feed or Weekly email newsletter
- Share on Twitter • Facebook • 3 comments... add one ↓
Category | List of Unix and Linux commands |
---|---|
File Management | cat |
Firewall | Alpine Awall • CentOS 8 • OpenSUSE • RHEL 8 • Ubuntu 16.04 • Ubuntu 18.04 • Ubuntu 20.04 |
Network Utilities | dig • host • ip • nmap |
OpenVPN | CentOS 7 • CentOS 8 • Debian 10 • Debian 8/9 • Ubuntu 18.04 • Ubuntu 20.04 |
Package Manager | apk • apt |
Processes Management | bg • chroot • cron • disown • fg • jobs • killall • kill • pidof • pstree • pwdx • time |
Searching | grep • whereis • which |
User Information | groups • id • lastcomm • last • lid/libuser-lid • logname • members • users • whoami • who • w |
WireGuard VPN | Alpine • CentOS 8 • Debian 10 • Firewall • Ubuntu 20.04 |
I think you should put more emphasis on handling special characters in file names, e.g. spaces. Personally I would have suggested the bottom-most approach using xargs, but to avoid errors -print0 should be used here too, in combination with the -0 / --null argument of xargs.
Using the pipe option and the -T will lead to an empty tar file in case the find comes empty which is probably not a desired outcome.
Hi,
I tested it on the GNU/Linux find and it cowardly refusing to create an empty archive:
find $HOME -type f -name "*.foobar" -print0 | xargs -0 tar cfvz /tmp/test.tar.gz
Here is what I got:
However, this might not work on BSD/tar or Solaris/HP-UX/AIX tar. YMMV.