使用 tar 解压缩: --exclude 太贪婪:如何仅排除根级文件?

使用 tar 解压缩: --exclude 太贪婪:如何仅排除根级文件?

我使用的是 Mac,El Capitan。

我的 zip 文件结构:

README.md
source/README.md

我似乎无法在不排除目录中的--exclude根级别的情况下进行操作。README.mdsource

我一直在尝试各种变化,例如:

# Doesn’t exclude anything:
tar -xf master.zip --strip-components 1 --exclude=/README.md
tar -xf master.zip --strip-components 1 --exclude=/{install.sh,README.md}

# Excludes both files:
tar -xf master.zip --strip-components 1 --exclude=./README.md
tar -xf master.zip --strip-components 1 --exclude={install.sh,README.md}
tar -xf master.zip --strip-components 1 --exclude=./{install.sh,README.md}

问题:

我怎样才能排除仅有的根级README.md

答案1

实际上,tar 可能会排除带有以下内容的文件--anchored

模式匹配文件名开始

但是你必须写出整个文件路径(它也会随着 改变cd):

$ cd /where/source/lives
$ tar -cf master.zip --anchored --exclude={source/install.sh,README.md} -- *

如果您需要一些灵活性,请使用 find。
可以使用此命令创建要压缩的文件列表,
拒绝! -name README.md基本README.md文件:

$ path="/path/to/files"
$ find "$path/" ! -path  "$path"/README.md -print

小心斜线/,它们确实很重要。如果其中包含要压缩的正确文件列表,则只需将其注入tar(添加到0-print创建tar命令):

find "$path/" ! -path  "$path"/README.md -print0 |
tar --no-recursion --null -T- --exclude=install.sh -v -cf master.zip

请注意,tar正在使用--null选项来匹配-print0of find

由于find提供了所需的所有递归,请使用 tar 的--no-recursion选项。

此外,该文件install.sh仍然被排除在tar(也可能已被删除find,但这只是个人喜好)。

在生产中,删除该-v选项以获得更简洁的 tar 命令。


要解压缩(而不是像上面那样压缩),请使用以下命令:

tar -xf master.zip --anchored --exclude={source/install.sh,README.md}

或者,如果您使用第二个选项创建压缩文件,排除的文件将不会在里面master.zip,您需要做的就是:

tar -xf master.zip    

答案2

有人可能会给出更好的答案,但如果 tar 的--exclude选项不能解决问题,您可以使用它find来生成文件列表,然后将其提供给tar.例如:

find * -path README.md -prune -o -print | 
tar --no-recursion -cf /tmp/data.tar -T-

这将打印非顶级的所有文件(和目录)的列表README.md,然后将它们提供给,后者从(使用)tar读取其文件列表。该标志是必要的,因为否则会自动包含目录中的所有文件,这是您不希望看到的,因为这些文件也将由 生成,并且您最终会在存档中得到多个具有相同名称的文件。stdin-T---no-recursiontarfind

更强大的版本可能如下所示:

find * -path README.md -prune -o -print0 | 
tar --no-recursion -cf /tmp/data.tar --null -T-

这里,-print0tofind--nulltotar表示文件名将由 ASCII NUL 字符而不是空格分隔,这意味着管道将处理包含空格的文件名。

答案3

pax实用程序具有比 BSD tar 更广泛的排除功能。它的-s选项允许您在存储或提取名称时转换名称,如果名称转换为空字符串,则该文件将被排除。

(BSD tar 有一个有点类似的-s选项,但根据文档,它似乎没有排除空功能。)

zcat foo.tar.gz | pax -r -pe -s'!^README\.md$!!' -s'!^\./README\.md$!!'

请注意,我假设是一个(可能是压缩的)tar 文件。如果您有 zip 文件,请使用unzip反而。

unzip foo.zip -x 'README.md'

相关内容