Ask Ubuntu is a question and answer site for Ubuntu users and developers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I currently have this script:

find . -iname '*.log' -print0 | xargs -0 tar zcf $file

To collect all the "*.log" files from a given directory. I would like to modify it to include also all the ".txt" files but I don't know how, this should be fairly simple right?

share|improve this question
up vote 2 down vote accepted

You are on the right way. Try this:

find . \( -iname "*.log" -or -iname "*.txt" \) -print0 | xargs -0 tar zcf $file

share|improve this answer
For some reason when I try it only find .txt if I remove the -prin0 | .... I get all the files listed though – OscarRyz Jan 4 '11 at 21:57
You are right. Add parenthesis before -print0. – Raphael Bossek Jan 4 '11 at 22:03
This will work up until a certain point. If the files found by find were to exceed the maximum argument length, xargs would pass as many files to tar as possible, then run it again with the remaining files. That means, the second tar would overwrite the archive the first tar made. – geirha Jan 20 '11 at 19:44
useless use of xargs – user unknown Mar 20 '11 at 0:46

This is almost the same as Raphael B.'s answer, but one that will also handle exceeding the maximum argument length. We do this by simply telling tar to read the filenames to archive from stdin (where there is no limit) instead of expecting them as arguments:

find . \( -iname "*.log" -o -iname "*.txt" \) -print0 | tar --null --files-from=- -zcf "$file"

Note that this is GNU specific. tar on other UNIX or UNIX-like systems does not understand --null, but the tar in Ubuntu is GNU tar, so it'll work fine there.

share|improve this answer
Good to know. BTW, I have this situation where the path is too long and it is not included in the search. To solve it I just cd to a closer path. Do you think this would help too in that situation? Eg I have /some/path/other/other/other/file1.txt and /some/path/other/other/other/file2.txt and so on. So, the command dropped anumber of files. To workaround it, I first cd /some/path/other/other and execute the search from there. – OscarRyz Jan 20 '11 at 21:44
Hm. The ancient tar format had a limitation on path length, but at least the posix tar format (pax) has no limitation. Not sure what format GNU tar uses by default. How long is the path that gives you problems though? Could you check with printf %s /some/path/other/other/other/file1.txt | wc -c ? Also, do you see which program gives the error message? find, xargs or tar? – geirha Jan 21 '11 at 8:14
Yes, well done geirha. Thanks... I tested it with large numbers of filenames, and using xargs is certainly a trap... It unforgivingly runs tar again and overwrites the previous .tar, which of course has the same name... What an easy way to lose a LOT of data and get no warning! .. other than yours :) – Peter.O Jan 21 '11 at 12:11

Here is the answer to useless use of xargs:

find \( -name "*.log" -or -name "*.txt" \) -exec tar zcf archiv2 {} + 

I didn't test it for a lot of files - would be glad about a comment and a number, where it fails.

The pseudoargument, that you need to remember to place the -delete as last: Well, yes, you too have to remember to put | xargs ... as last, don't you?

share|improve this answer

What about this very simple approach:

find -iname '*.txt'; find -iname '*.log'
share|improve this answer
find . -regextype posix-extended -iregex '.*\.(log|txt)' -print0 | xargs -0 tar zcf $file

You can replace the '.*\.(log|txt)' with any POSIX Extended regular expression.

The example matches:

Any number of any character

then a '.'

then 'log' or 'txt'

share|improve this answer
I got: find: invalid predicate -regextype but this lead me to a working version find . -regex '.*\.\(log\|txt\)' -print0 ...etc – OscarRyz Jan 4 '11 at 21:59
That's strange. It works fine for me but doesn't match unless I specify the regexp type as posix-extended, awk, gnu-awk or posix-egrep using the -regextype parameter . – dv3500ea Jan 4 '11 at 22:10

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.