find命令查找特定文件,并通过-exec 选项将其按照原来的目录树打包成压缩文件

 

find ./ -type f -name "*.iso" -exec tar -cvf out_archive.tar {} + ;

 

$ ls
libdisk.o  part_amiga.c  part.c      part_dos.h  part_efi.c part_efi.o  part_iso.h  part_mac.h
Makefile   part_amiga.h  part_dos.c  part_dos.o  part_efi.h  part_iso.c  part_mac.c part.o

 

$find ./ -type f -name "*.o" -exec tar -cvf out_archive.tar {} + ;
./part.o
./part_efi.o
./libdisk.o
./part_dos.o

 

 

$ tar xvf out_archive.tar
./part.o
./part_efi.o
./libdisk.o
./part_dos.o

 

 

使用如下命令,也会生成一个压缩包(archivetxt1.tar)。但是,这个压缩包,实际上没找到一个文件,就单独压缩这个文件,所以,实际上每次压缩覆盖了前一次,所以最后压缩包中只有最后找到的那个txt文件。

$ find . -type f -name "*.txt" -exec tar-cvf archivetxt1.tar '{}' \;
./employe.txt
./file.txt
./file2.txt
./files.txt
./filesfound.txt
./sql.txt
./users.txt

$ tar -tvf archivetxt1.tar
-rwxrwxrwx chaitanya/None    6 2012-02-15 16:35 ./users.txt

 

我们只需要改tar 命令的一个参数(-u),就可以实现每个找到的文件都包含在最后的压缩包中了。因为下一次压缩找到的那个文件的时候,它不会覆盖同名的压缩包,而是在原有同名压缩包的基础上把新找到的文件压缩进去。

 

find ./ -type f -name "*.txt" -exec tar -uf myarchives.tar '{}' \;
tar -tvf myarchives.tar

 

所以这个命令( find ./ -type f -name "*.txt" -exec tar -uf myarchives.tar '{}' \; )与( find ./ -type f -name "*.o" -exec tar -cvf out_archive.tar {} + ;)这个命令的最终效果是等价的。

 

我们看tar命令的帮助文档,可以找到如下命令格式:

SYNOPSIS
     tar [-] A --catenate --concatenate | c --create | d --diff --compare | --delete | r --append | t
         --list | --test-label | u --update | x --extract --get [options] [pathname ...]

那么实际上,我们还可以再tar命令中来使用 append这个选项(简写r)来实现同样的功能:

find ./ -type f -name "*.txt" -exec tar -rf myarchives.tar '{}' \;
tar -tvf myarchives.tar

-r 选项会在压缩文件的尾部追加新找到的文件。

 

 

另外我们要注意到 本文第一个命令的实现在查找到的文件很多的时候,即+号带来的入参太多的话,是存在很大的问题的,他能处理的参数个数是有限的:

Quote:
Originally Posted by   alister   View Post
Keep in mind that if the size/number of the matching filenames exceeds what can be passed to tar in one invocation, that will silently revert to the original problem, of tar clobbering the archive generated by the previous iteration.

For archiving files found with find,   pax    or   cpio    are much more convenient than tar, since they can read the list on stdin.
对于在find中找到的文件,要被压缩的话,最好是使用pax 或是 cpio命令,他们比tar命令更为方便和可靠,因为他们可以从stdin读列表。

Regards,
Alister
Exactly, there is a problem if the number of txt existing files exceed the maximum number of arguments that can be handled. For example this will fail on my system:


Code:
for i in {1..50000}; do echo >  file-$i.txt ; done
find ./ -type f -name "file-*.txt" -exec tar -cf txtarchive.tar {} + ;

上面第一行是生成5万个 txt文件;

第二个是使用带+的命令来把这些所有的txt文件压缩到一个压缩包。


There are 50000 txt files in dir:

Code:
find ./ -name "file-*.txt" | wc -l
50000


While in the tar there are only 3138 and no error was shown:

前面我们实际上有50000个txt文件。但实际上,被tar压缩进压缩文档的,只有3138个文件(wc是统计个数的)。

Code:
tar -tf txtarchive.tar  | wc -l
3138


-----------
On the other hand, independent exec with find for each argument is terribly slow when the number of arguments is high.

Could you provide examples with pax  or cpio ? 

 

更好的办法是使用pax 或 cpio命令来实现压缩文档:

          具体方法请参考       在find中使用pax或cpio 命令来实现将找到的所有文件压缩到一个压缩包 

                                             http://blog.csdn.net/duanlove/article/details/8264034



 

参考:

    UNIX论坛  http://www.unix.com/shell-programming-scripting/193651-xargs-vs-exec-find.html

 

你可能感兴趣的:([Linux_app])