I'm looking for a nice way to generate a backup tar.gz of what is going to be overridden by the extraction of another tar.gz.

tar -ztf patch.tar.gz | grep -v "/$" | tar -T- -zcvf backup.tar.gz

This works perfectly! However, sometimes, the new patch (patch.tar.gz) will not only contain files already existing in the HDD, but also may add new files which don't already exist. These files which don't exist will be impossible to backup, and the second tar will generate an error. The exit code is 2.

tar: folder/file.txt: Cannot stat: No such file or directory
tar: Exiting with failure status due to previous error

I'm looking for shell command which only checks for file existence (stdin) et send existing files on stdout. Does it exist? I would need something like this:

tar -ztf patch.tar.gz | grep -v "/$" | filterfileexist | tar -T- -zcvf backup.tar.gz

I need one shell command and not a shell script.
Obviously, I could implement this shell command in C myself, because it's very simple, but I hope to find something generic which will be found on other UNIX platforms.

3 Answers 3


Try use perl oneliner for this


cat filelist | perl -ne 'chomp(); if (-e $_) {print "$_\n"}' | tar -T- -zcvf backup.tar.gz
  • you can also use other testing conditions in perl oneliner. for example if (-r $_) will filter only exists and readable by current user files. Full list conditions see at perldoc
    – Nik
    Commented Jul 3, 2014 at 16:00
  • 1
    It was supposed to be a shell command, not a perl program specified on command line and introducing a dependency on perl. Commented Jan 26, 2021 at 11:38
  • Downvoted for pulling in the entirety of the perl behemoth just to solve a tiny problem. Commented Jul 10, 2021 at 10:19

Here are a couple of alternatives.

tar -ztf patch.tar.gz | grep -v "/$" | xargs -i sh -c 'test -f {} && echo {}' | tar -T- -zcvf backup.tar.gz


tar -ztf patch.tar.gz | grep -v "/$" | tar --ignore-failed-read -T- -zcvf backup.tar.gz

The second example will exit with status zero after an attempt to backup a file that does not exist (tested on Centos 6.5), which avoids the problem.

  • The first one is nice! Thanks! About the second one: I have already tried '--ignore-failed-read', but the problem is that it doesn't only ignore failed reads on the -T files. It ignores all failed reads.
    – Fox
    Commented Jul 3, 2014 at 15:21

Use find with xargs. Default behavior of find is to print filename to stdout if the file exists, non-existing files will have an error message printed to stderr

$ echo existing-file missing-file | xargs find 2> /dev/null
./exisisting file

If there are directories, add -type f or -maxdepth=0 to prevent find from default recursion.

$ echo existing-file missing-file dir | xargs -I% find % -type f 2> /dev/null
./exisisting file

The usual whitespace caveat applies. Safer version

$ echo existing-file missing-file 'annoying
name sudo rm -rf /' | tr '\n' '\0' | xargs -0 find 2> /dev/null
  • The problem with this is that $ find fails when given non existent file. It returns a non-zero exit code. Commented Sep 27, 2023 at 23:48
  • @RossPatterson if that's a problem then find ... || true, and in a pipe { find ... || true ;}
    – CervEd
    Commented Sep 28, 2023 at 7:18
  • Of course, but that ignores why $ find failed and exited with a non-zero status which was a problem for the case that brought me to reading this question's answers. Hence my comment for others that may get here with similar cases. Commented Sep 29, 2023 at 11:53

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .