2

I am trying to tar multiple files using the find command. I want to find all the files in the directory that contain a specific string in the file name and then tar those files. The string that I am want to find in the file name is the date.

For instance, I have a file name named ulog.20120914.log

What I'm doing right now is:

DAYTWOPREV=`date +%Y%m%d --date='2 days ago'`

function archive {
    cd $1;
    if [ ! -d archive ]; then
        mkdir archive;
    fi

TMPFILE=`mktemp`;
    find . -maxdepth 1 -name "${DAYTWOPREV}*" -type f -print0  > $TMPFILE;


    TARFILE=archive/${DAYTWOPREV}$2.tar;
    if [ ! -e $TARFILE ]; then
        echo tar cfT $TARFILE /dev/null;
        tar cfT $TARFILE /dev/null;
    fi  

cat $TMPFILE | xargs -0r tar rf $TARFILE
    cat $TMPFILE | xargs -0r rm -rf
    rm -f $TMPFILE;

}
4

4 回答 4

3

You can tell GNU tar to read the list of files to archive from its standard input:

find . -maxdepth 1 -name "${DAYTWOPREV}*" -type f | tar -czf archive.tar.gz -T -

The -T - is the magic; -T means 'read file list from given file', and the (second) - indicates 'the file is standard input'. (I added the z option to compress the file using gzip and named the tar file accordingly. You might prefer j and bzip2 with the .bz2 extension. You might find your tar supports xz compression natively; the option letter is -J on Mac OS X and BSD. And BSD supports --lzma for LZMA compression.)

Also, with GNU tar, you can specify option --null (and then with GNU find use -print0) to handle even file names containing newlines. As written, this runs into issues if the file names contain newlines; otherwise, it works one file per line reliably enough, spaces and all.

于 2012-09-18T15:23:12.560 回答
3

Assuming you have GNU tar (i.e. on Linux, not AIX, or HP-UX or ...):

find . -maxdepth 1 -type f -print0 | grep -z "${DAYTWOPREV}" | tar -cvf archive.tar --null -T /dev/stdin
于 2012-09-18T15:27:22.410 回答
0

Incidentally, tar does have an option (r instead of c) that fixes the "multiple invocations of tar" problem with some of these other solutions.

find . -maxdepth 1 -name '*20120914*' -exec tar rvf archive.tar {} +

find . -maxdepth 1 -name '*20120914*' -print0 | xargs -0 tar rvf archive.tar

Actually, it looks like you're already using that. What exactly is missing from your existing solution? (Other than - I don't think you actually need the tar file to exist, so the /dev/null creation is an unnecessary step. However, I'm not in a position to test right now)

于 2012-09-18T15:43:27.353 回答
0

I would just do this:

tar -cf $TARFILE ${DAYTWOPREV}*
于 2012-09-18T15:52:48.087 回答