tar命令用法示例
2014-03-11 12:18:22

tar命令用来将很多文件打包成一个单一的磁带或者磁盘归档,并可从归档文件恢复出文件列表。它与通常与压缩指令相结合来使用,这里介绍一些基本的使用场景。

tar的语法:
# tar [options] file.tar file1 file2 .. .. ..
file.tar 是 tar 归档文件,而其他 file1 和 file2 等等是要被打包的文件。

例如我们有两个文件 file1.txt 和 file2.txt

[root@localhost FreeOA]# ll
total 8
-rw-r--r--. 1 root root 2770 Feb  7 22:37 file1.txt
-rw-r--r--. 1 root root  887 Feb  7 22:38 file2.txt

tar常用的使用场景

创建一个 tar 文件
语法:
# tar -cf archive.tar files .. ..
示例:
[root@localhost FreeOA]# tar -cf file.tar file1.txt file2.txt
[root@localhost FreeOA]# ll file.tar
-rw-r--r--. 1 root root 10240 Feb  7 22:42 file.tar

列出tar文件中的所有文件列表
# tar -tf archive.tar
示例:
[root@localhost FreeOA]# tar -tf file.tar
file1.txt
file2.txt

从tar中提取所有文件
tar -xf archive.tar

示例:
[root@localhost FreeOA]# tar -xf file.tar
# ll
total 20
-rw-r--r--. 1 root root  2770 Feb  7 22:37 file1.txt
-rw-r--r--. 1 root root   887 Feb  7 22:38 file2.txt
-rw-r--r--. 1 root root 10240 Feb  7 22:42 file.tar

参数选项:

1、-v, –verbose
verbosely list files processed:
Syntax:
List all files in an archive.tar verbosely:
tar -tvf archive.tar

示例(列出包中的文件):
[root@localhost FreeOA]# tar -tvf file.tar
-rw-r--r-- root/root      2770 2014-02-07 22:37 file1.txt
-rw-r--r-- root/root       887 2014-02-07 22:38 file2.txt

2、-c, –create
创建新的归档文件

3、-t, –list
列出归档文件中的内容

4、-x, –extract, –get
从归档中提取文件

5、-d, –diff, –compare
比较归档和文件系统的差异
示例:
[root@localhost FreeOA]# tar -tf file.tar
file2.txt
file3.txt
file1.txt
[root@localhost FreeOA]# tar -df file.tar file1.txt file2.txt file4.txt
tar: file4.txt: Not found in archive
tar: Exiting with failure status due to previous errors
----Verbosely----
[root@localhost FreeOA]# tar -dvf file.tar file1.txt file2.txt
file2.txt
file1.txt
[root@localhost FreeOA]# tar -dvf file.tar file1.txt file2.txt file6.txt
file2.txt
file1.txt
tar: file6.txt: Not found in archive
tar: Exiting with failure status due to previous errors

6、–delete
从归档中删除某文件
示例:
从归档 file.tar 中删除 file1.txt
[root@localhost FreeOA]# tar -f  file.tar --delete file1.txt
[root@localhost FreeOA]# tar -tf file.tar
file2.txt

7、-r, –append
追加文件到归档中
示例:
追加 file3.txt 到 file.tar
[root@localhost FreeOA]# tar -f archive.tar -r new/test2.txt
[root@localhost FreeOA]# tar -rf file.tar file3.txt
[root@localhost FreeOA]# tar -tf file.tar
file1.txt
file2.txt
file3.txt
new/test2.txt

8、-A, –catenate, –concatenate
将一个tar 归档追加到另外一个归档文件中,创建另外一个tar文件
[root@localhost FreeOA]# tar -cf archive.tar file1.txt file3.txt
追加方法:
[root@localhost FreeOA]# tar -Af file.tar archive.tar
[root@localhost FreeOA]# tar -tf file.tar
file2.txt
file3.txt
file1.txt
file1.txt
file3.txt

9、–test-label
测试归档卷标并退出

10、-u, –update
只追加最新的文件

示例:
[root@localhost FreeOA]# tar -tf file.tar
file1.txt
file2.txt

[root@localhost FreeOA]# tar -uf file.tar file1.txt file3.txt file2.txt

# tar -tf file.tar
file1.txt
file2.txt
file3.txt

11、 -C, –directory=DIR
将文件输出到指定的目录DIR

示例:
提取文件到另外一个目录
[root@localhost FreeOA]# tar -xvf file.tar -C /root/FreeOA2
file1.txt
file2.txt
[root@localhost FreeOA]# cd -
/root/FreeOA2
[root@localhost FreeOA2]# ll
total 28
-rw-r--r--. 1 root root 23250 Feb  7 23:11 file1.txt
-rw-r--r--. 1 root root   887 Feb  7 22:38 file2.txt

将指定的test2.txt文件从包中释放到指定的目录(new)下
# tar -xf archive.tar -C new/ test2.txt

注意:目标目录必须在释放前必须先存在,如果不存在必须要先创建。

12、-p, –preserve-permissions
抽取文件时保留原有的文件权限

压缩归档文件,默认就可使用 BZIP 和 GZIP 两种方法,还支持gz,bzip2,xz,lzip,lzma,xz这些方法,目前还没有对zstd提供直接的支持,可以通过管道实现:
# tar cf -  /target/directory|zstd -9 -v -o freeoa.tar.zst

跟压缩相关的参数

13、-j, –bzip2
使用 bzip2 对归档进行压缩

示例:
[root@localhost FreeOA]# tar -jcf file.tar.bz file2.txt file1.txt
# ll
total 128
-rw-r--r--. 1 root root 23250 Feb  7 23:11 file1.txt
-rw-r--r--. 1 root root   887 Feb  7 22:38 file2.txt
-rw-r--r--. 1 root root 30720 Feb  7 23:30 file.tar
-rw-r--r--. 1 root root  1797 Feb  7 23:42 file.tar.bz
请看,上面的文件大小通过 BZIP 降低到 1797 字节。

14、-z, –gzip
使用 gzip 压缩归档

示例:
[root@localhost FreeOA]# tar -zcf file.tar.gz file2.txt file1.txt
# ll
total 132
-rw-r--r--. 1 root root 23250 Feb  7 23:11 file1.txt
-rw-r--r--. 1 root root   887 Feb  7 22:38 file2.txt
-rw-r--r--. 1 root root 30720 Feb  7 23:30 file.tar
-rw-r--r--. 1 root root  1797 Feb  7 23:42 file.tar.bz
-rw-r--r--. 1 root root  1673 Feb  7 23:45 file.tar.gz

15、Disable Directory Recursion(禁止目录的递归)
# tar -czf etc-no-dirs.tar.gz /etc/* --no-recursion


16、Keep Newer Files(保留包中的较新的文件)
# tar -xf archive.tar test2.txt --keep-newer-files

tar: Current 'test2.txt' is newer or same age


17、Remove Files After Archiving(在成包后删除源文件)
# tar -cvf archive.tar test1.txt test2.txt --remove-files

18、Exclude Files By Pattern(用指定的模式排除一些文件)
# tar -cvf exclude.tar --exclude=*.mp3 *


19、Confirm Before Adding Files(在处理时进行确认)
# tar -cwf confirm.tar *
add `test1.txt'?n
add `test2.txt'?y
add `z.mp3'?y

# tar -tf confirm.tar
test2.txt
z.mp3

# tar -xwf confirm.tar
extract `test2.txt'?n
extract `z.mp3'?y

20、POSIX ACL Support(ACL属性支持)
POSIX ACL support for files within the archive can be enabled with the --acls option or disabled with the --no-acls option, --no-acls is used by default so if we want ACL support it must be specified.

# setfacl -m u:user1:rw test1.txt
# getfacl test1.txt
# file: test1.txt
# owner: root
# group: root
user::rw-
user:user1:rw-
group::r--
mask::rw-
other::r--

# tar -cf acls.tar test1.txt --acls
# rm -fv test1.txt
# tar -xf acls.tar

# getfacl test1.txt
# file: test1.txt
# owner: root
# group: root
user::rw-
user:user1:rw-
group::r--
mask::rw-
other::r--

# rm -f test1.txt
# tar -xf acls.tar

# getfacl test1.txt
# file: test1.txt
# owner: root
# group: root
user::rw-
group::rw-
other::r--


21、Extended Attribute Support(推展属性支持)

For files within the archive can be enabled with the --xattrs option or disabled with the --no-xattrs option.

# tar -cf xattrs.tar test1.txt --xattrs


22、SELinux Support

SELinux support for files within the archive can be enabled with the --selinux option or disabled with the --no-selinux option.

# tar -cf no-selinux.tar * --no-selinux


23、Set New User/Group Owner Of Archived Files(设置包中新的用户或组)

We can set the user and/or group owner of a file when adding it into the archive with --owner=name to force new owner and --group=name to force a new group for the added files.

# tar -cf user-group-change.tar test2.txt --owner=user1 --group=user1

Now once we extract this file the user and group should be set to user1, rather than root.

# tar -xf user-group-change.tar
# ls -l
total 3364
-rw-rw-r--. 1 root  root       52 Sep  2 12:24 test1.txt
-rw-r--r--. 1 user1 user1      25 Sep  2 14:02 test2.txt


24、Extract Files To Standard Output(将文件释放到标准输出)

tar 解包出来的文件输出到文件流(pipe contents of large tar.gz file to STDOUT)

Use this with GNU tar to extract a tgz to stdout:
tar -xOzf large.tar.gz --wildcards '*.html' | grep ...
-O, --to-stdout: extract files to standard output

Rather than extracting files from within the tar file to the file system, we can simply send them to stdout instead with the -O option which may be useful if we just want to quickly read the contents of a file without having to extract it first.

# tar -xOf archive.tar test1.txt
This is test1.txt
# tar -xOf archive.tar test2.txt
This is test2.txt

将tar.gz包中文件的内容(注意:是文件内容)重新压制成zst包(与预期并不相符):
tar -xOzf freeoa.tar.gz | zstd -f -9 -v -T9 -B32 -o freeoa.zst


25、Check Archive File(检查归档包的指定文件)

We can attempt to verify an archive file during creation with the -W option.

# tar -cvWf archive.tar test1.txt test2.txt
test1.txt
test2.txt
Verify test1.txt
Verify test2.txt

26、解包过程中移除或添加tar包中记录的顶级目录

如果想在释放的过程中移除tar包中的顶级目录,可做如下操作:
If your tarball already contains a directory name you want to change, add the --strip-components=1 option:
tar xf archive.tar -C /target/directory --strip-components=1

To extract and also remove the root(first level) directory in tar
mkdir -p /target/directory && tar xf archive.tar -C /target/directory --strip-components=1

The option --one-top-level will automatically create a directory based on the filename of the original.
即使在打包时没有从其中文件的上层目录开始,使用--one-top-level选项可以帮助创建打包前的上级目录并在其下释放文件。
tar xvzf filename.tgz --one-top-level

还可以指定以新的目录名称替换前上级目录
tar xvzf filename.tgz --one-top-level=new_directory


27、目录下大量文件的间接处理

# cd /freeoa
# tar -cvf /tmp/freeoa_temp_bf220419.tar temp/* --remove-files
-bash: /usr/bin/tar: Argument list too long
# ls temp/ > list.temp.txt
# cd temp/
# tar -cvf  /tmp/freeoa_temp_bf220419.tar -T /freeoa/list.temp.txt --remove-files

操作过程:将其目录下的文件列出到一列表文件中,tar命令从文件中读取相关的文件列表后再从目录中分批取文件处理。


28、通过管道将数据流传给其它命令处理

多见于使用压缩指令完成对包的压缩:
tar cf - dir | gzip -9 > somedir.tar.gz

#将mysql-test目录打包压缩存档
tar -cf - mysql-test|zstd -19 -o mysql-test.tar.zst

如果tar的版本支持的话,还可以在处理(打包压缩)前进行其它的操作:
If you have the version that supports member transforms (--transform or --xform) then you can simply do.
使用transform对文件进行重命名。

tar -c --transform=s/vim/vi/ url.txt vim.txt  | gzip -9 > freeoa.tar.gz

或直接使用'-z'调用压缩软件处理
$ tar -czvf freeoa.tar.gz --transform=s/url/links/ url.txt vim.txt
url.txt
vim.txt

$ tar -tvzf freeoa.tar.gz
-rw-r--r-- hto/hto        1300 2022-06-19 12:04 links.txt
-rw-r--r-- hto/hto        5779 2022-06-19 12:04 vim.txt


29、更多压缩选项
对13、14、28小节的联合补充。

通过设定Shell环境变量可以实现对压缩比率的指定
Gz
GZIP=-9 tar cvzf file.tar.gz /path/to/directory

Xz
现代版本的tar支持z档案格式(GNU tar, since 1.22 in 2009,Busybox since 1.17.0 in 2010).
tar -Jcvf file.tar.xz /path/to/directory
xz_OPT=-9 tar -Jcvf file.tar.xz /path/to/directory

或间接通过管道实现压缩比率的指定
tar cv /path/to/directory | gzip --best > file.tar.gz
tar cvf - /path/to/file0 /path/to/file1 | gzip -9 - > files.tar.gz
tar -cvf files.tar /path/to/file0 /path/to/file1 ; gzip -9 files.tar

较新版本的tar指令可以通过其指令参数调用外部的压缩命令进行处理,在1.34版本中的帮助中有如下的参考,压缩选项:
-a, --auto-compress    使用归档后缀名来决定压缩程序
-l, --use-compress-program=PROG    通过PROG过滤(必须是能接受-d选项的程序)
-j, --bzip2    通过bzip2过滤归档
-J,--Xz    通过xz过滤归档
--lzip    通过Izip过滤归档
--lzma    通过xz过滤归档
--lzop    通过lzop过滤归档
--no-auto-compress    不使用归档后缀名来决定压缩程序
--zstd    通过zstd过滤归档
-z,--gzip,--gunzip,--ungzip    通过gzip 过滤归档
-Z,--compress, --uncompress    通过compress过滤归档

可以看到能直接调用zstd的压缩工具了。如果不支持,可以使用'-I'来实现(不过更多的压缩工具选项可能不被支持,如压缩比率)。
tar -l 'gzip -9' -cvf file.tar.gz /path/to/directory
tar --use-compress-program='gzip -9' -cvf file.tar.gz /path/to/directory

tar -I 'gzip -9' -cvf /tmp/z1.tgz freeoa
tar (child): gzip -9:无法 exec: 没有那个文件或目录
tar (child): Error is not recoverable: exiting now

另外还需要注意,Tar的实现分为GNU tar与BSD tar,它们在使用上还是有一定的区别,注意阅读其手册页。在BSD系统可以进一步通过选项指定:
tar -czf file.tar.gz --options gzip:compression-level=9 /path/to/directory

Zstd压缩算法有:zstd:compression-level来指定压缩比率。

从此处看,BSD比GNU要更用心些。

30、与find指令执行联合任务

先看一个执行不成功的示例(只为最后一个文件建立了tar包):
find ./ -type f -mtime +90 -exec tar -cvf /tmp/file.tar {} \;

Note that find will call the -exec action for every single file it finds.
请注意,find将为它找到的每个文件调用-exec操作。

如果对每个文件查找输出运行tar-cvf file.tar {},这意味着每次都会覆盖file.tar,这就解释了为什么最后只剩下一个只包含符合条件的归档文件——这是最后一个文件查找输出。现在实际上想要将文件附加到归档中,而不是每次都创建它(这正是-c选项所做的)。因此请使用以下内容:
find var/log/ -iname "freeOa.*" -exec tar -rvf /tmp/file.tar {} \;

-r选项会附加到存档中,而不是每次都重新创建它:
find ./ -type f -mtime +99 -exec tar -rvf /tmp/freeoa.bf.230727.tar {} +
find ./ -type f -mtime +99 -exec tar -rvf /tmp/freeoa.bf.230727.tar {} \;

#safe option to deal with file names,文件名中包含了特殊字符(white spaces or wild characters)等
find ./ -type f -mtime +90 -print0 | tar -cvf /tmp/freeoa.bf.230728.tar --null -T -
find $HOME -name "*.doc" -print0 | tar -cvf /tmp/file.tar --null -T -

The --null and -T - option tells the tar command to read its input from stdin or pipe. Use the xargs command:
find $HOME -type f -name "*.sh" -print0 | xargs -0 tar cfvz /tmp/freeoa-shellscripts.tgz

可将find做为一个子命令输出来使用
#归档后用'--remove-files'来删除相关的文件

find ./ -type f -mtime +95 -exec tar -rvf /tmp/freeoa.bf.230795.tar --remove-files {} \;

tar -cvf /tmp/freeoa.bf.230729.tar `find ./ -type f -mtime +90`

tar -cvf /tmp/freeoa.bf.230790.tar `find ./ -type f -mtime +90` --remove-files

tar -cvzf jpng.images.tar.gz $(find /home/user -iname "*.jpg" -o -iname "*.png")

利用shell变量存放要处理的文件列表:
PLS=$(find . -name "*.pl") && tar cvf useful.pl.tar $PLS

## find all *.sh (shell scripts) and run ls -l command on it
find . -iname "*.sh" -exec ls -l {} +

## Safe search options for xargs or tar
find /path4dir/ -name "*.jpg" -print0

由于文件名中可能有的一些特殊字符,因此find也为此种情况提供了相应和命令选项:
-print0 : Let us print the full file name on the standard output (screen), followed by a null character (instead of the newline character that -print uses) with the find command. This allows file names that contain newlines or other types of white space to be correctly interpreted by programs that process the find output. This option corresponds to the -0 option of xargs.

-0 or --null : Input items are terminated by a null character instead of by whitespace, and the quotes and backslash are not special (every character is taken literally). Disables the end of file string, which is treated like any other argument. Useful when input items might contain white space, quote marks, or backslashes. The GNU find -print0 option produces input suitable for this mode.

find /path/ -name "file-pattern" -print0 | xargs -0 tar cvfz tarball.gz