How do I find all files in a folder(including subfolders) with extension jpg or bmp, with size between 6 and 46 kilobytes, last modified between 11 and 19 June 2011 or between 24 July and 2 August inclusively and add all these files to an archive(bzip2)?
1 Answer
You can try a similar command (but it actually has a flaw):
$ find . \( -name "*.jpg" -o -name "*.bmp" \) -and \( -size +6k -and -size -46k \) -and \( \( -newermt "2011-06-11" -and ! -newermt "2011-06-19" \) -or \( -newermt "2011-07-24" -and ! -newermt "2011-08-02" \) \) -print0 | xargs -0 tar cjf out.tar.bz2 --files-from=-
Not sure about the dates, though. It works for me as YYYY-MM-DD
but it might change with the language settings.
Update:
There is a major conceptual mistake in the previous example.
Basically the xargs
command works in „passes” (eg. takes as much filenames as possible to cram into a command line and calls the tar
command). So out.tar.bz2
gets rewritten at every pass.
It may not be noticed with a few dozen test files, but a few hundred will trigger the bug for sure. So the command needs to be rewritten as follows:
$ find . \( -name "*.jpg" -o -name "*.bmp" \) -and \( -size +6k -and -size -46k \) -and \( \( -newermt "2011-06-11" -and ! -newermt "2011-06-20" \) -or \( -newermt "2011-07-24" -and ! -newermt "2011-08-03" \) \) -print0 | tar cjf out.tar.bz2 --null --files-from=-
The main difference is the absence of xargs
and using the --null
option for tar
. This option will tell tar
to read null terminated filenames (as produced by the find
commands -print0
option). The whole reason behind these null terminated filenames are to avoid filenames containing special characters (eg. whitespace), that would otherwise break the tar
command.
Another possible bug to point out is the date range specification. The upper end of date range should be increased by 1 day (otherwise files modified on that day will be omitted).
-
@johnny Found a major flaw in the implementation, fix posted with explanation.– lgarzoCommented Jan 6, 2012 at 17:46