如何使用 tar 命令排除特定文件?
How to exclude specific files with the tar command?
假设我有以下目录结构
dir/
├── subdir
│ ├── dir
│ │ └── TODO.txt
│ └── TODO.txt
└── TODO.txt
我希望在 Linux 上使用命令 tar
将 dir/
递归地打包到 tarball 中,但是 我想排除根 TODO.txt 。我如何用相对路径指定它?
尝试 #1
tar -czf dir.tar.gz dir/ --exclude='TODO.txt'
不起作用:它摆脱了生成的 tarball 中的 every TODO.txt:
dir/
└── subdir
└── dir
尝试#2
tar -czf dir.tar.gz dir/ --exclude='dir/TODO.txt'
这也失败了,因为 dir
子目录也与此模式匹配。因此生成的 tarball 包含
dir/
└── subdir
├── dir
└── TODO.txt
有什么方法可以准确指定我想用相对路径排除根 TODO.txt 吗?
来自@arkascha 的回答:
find dir/ -type f | grep -v "^dir/TODO.txt" > files.txt
然后
tar -czf dir.tar.gz -T files.txt
从第一行开始,有2个技巧需要注意:
-type f
选项。如果不放置,目录将包含在 find
的结果中。这很糟糕,因为它包含每个文件的次数与它们在文件层次结构中的深度一样多。
grep
的正则表达式中的 ^
:它确保我们从文件层次结构的开头排除模式
不要使用 dir/
来命名您的传输,而是 cd 到 dir
,然后将其命名为 .
。文件夹名称 .
将永远不会出现在任何文件路径中,因此它可以作为一个强大的锚点。然后使用 --transform=
,使存档中的路径以 dir/
.
开头
演示
没有过滤器:
$ tar -czf dir.tar.gz -v dir
dir/
dir/TODO.txt
dir/subdir/
dir/subdir/TODO.txt
dir/subdir/dir/
dir/subdir/dir/TODO.txt
cd 进入 dir
,将其命名为 .
:
$ tar -czf dir.tar.gz -v -C dir .
./
./TODO.txt
./subdir/
./subdir/TODO.txt
./subdir/dir/
./subdir/dir/TODO.txt
排除,锚定在.
:
$ tar -czf dir.tar.gz -v -C dir --exclude='./TODO.txt' .
./
./subdir/
./subdir/TODO.txt
./subdir/dir/
./subdir/dir/TODO.txt
在存档中将 .
改回 dir
(--show-transformed-names 使 tar
在进入存档时显示名称):
$ tar -czf dir.tar.gz -v -C dir --exclude='./TODO.txt' --transform='s/^\./dir/g' --show-transformed-names .
dir/
dir/subdir/
dir/subdir/TODO.txt
dir/subdir/dir/
dir/subdir/dir/TODO.txt
假设我有以下目录结构
dir/
├── subdir
│ ├── dir
│ │ └── TODO.txt
│ └── TODO.txt
└── TODO.txt
我希望在 Linux 上使用命令 tar
将 dir/
递归地打包到 tarball 中,但是 我想排除根 TODO.txt 。我如何用相对路径指定它?
尝试 #1
tar -czf dir.tar.gz dir/ --exclude='TODO.txt'
不起作用:它摆脱了生成的 tarball 中的 every TODO.txt:
dir/
└── subdir
└── dir
尝试#2
tar -czf dir.tar.gz dir/ --exclude='dir/TODO.txt'
这也失败了,因为 dir
子目录也与此模式匹配。因此生成的 tarball 包含
dir/
└── subdir
├── dir
└── TODO.txt
有什么方法可以准确指定我想用相对路径排除根 TODO.txt 吗?
来自@arkascha 的回答:
find dir/ -type f | grep -v "^dir/TODO.txt" > files.txt
然后
tar -czf dir.tar.gz -T files.txt
从第一行开始,有2个技巧需要注意:
-type f
选项。如果不放置,目录将包含在find
的结果中。这很糟糕,因为它包含每个文件的次数与它们在文件层次结构中的深度一样多。grep
的正则表达式中的^
:它确保我们从文件层次结构的开头排除模式
不要使用 dir/
来命名您的传输,而是 cd 到 dir
,然后将其命名为 .
。文件夹名称 .
将永远不会出现在任何文件路径中,因此它可以作为一个强大的锚点。然后使用 --transform=
,使存档中的路径以 dir/
.
演示
没有过滤器:
$ tar -czf dir.tar.gz -v dir
dir/
dir/TODO.txt
dir/subdir/
dir/subdir/TODO.txt
dir/subdir/dir/
dir/subdir/dir/TODO.txt
cd 进入 dir
,将其命名为 .
:
$ tar -czf dir.tar.gz -v -C dir .
./
./TODO.txt
./subdir/
./subdir/TODO.txt
./subdir/dir/
./subdir/dir/TODO.txt
排除,锚定在.
:
$ tar -czf dir.tar.gz -v -C dir --exclude='./TODO.txt' .
./
./subdir/
./subdir/TODO.txt
./subdir/dir/
./subdir/dir/TODO.txt
在存档中将 .
改回 dir
(--show-transformed-names 使 tar
在进入存档时显示名称):
$ tar -czf dir.tar.gz -v -C dir --exclude='./TODO.txt' --transform='s/^\./dir/g' --show-transformed-names .
dir/
dir/subdir/
dir/subdir/TODO.txt
dir/subdir/dir/
dir/subdir/dir/TODO.txt