将输出馈送到 tar 时忽略“查找”中的过滤器

Int*_*lIV 6 tar find recursive

我有以下目录结构:

test/
test/1/
test/foo2bar/
test/3/
Run Code Online (Sandbox Code Playgroud)

我想压缩目录“test”,不包括子目录中的所有内容(深度未预定义),其中包括字符串“1”或“2”。在 bash shell 中,我想使用find并将其输出提供给tar。我首先测试发现

find test/ -not -path "*1*" -not -path "*2*"
Run Code Online (Sandbox Code Playgroud)

输出:

test/
test/3
Run Code Online (Sandbox Code Playgroud)

伟大的。所以我将它与tar结合起来:

find test/ -not -path "*1*" -not -path "*2*" | tar -czvf test.tar.gz --files-from -
Run Code Online (Sandbox Code Playgroud)

输出:

test/
test/3/
test/1/
test/foo2bar/
test/3/
Run Code Online (Sandbox Code Playgroud)

事实上,“test/1”和“test/foo2bar”都存在于档案中。如果这些参数不应该出现在 find 输出中,为什么要传递给 tar?

lar*_*sks 11

为了扩展@cuonglm 所说的内容,tar默认情况下以递归方式运行。如果您传递给它一个目录名,它将归档该目录的内容

您可以修改您的find命令以仅返回文件名,而不是目录...

find test/ -type f -not -path "*1*" -not -path "*2*" |
tar -czvf test.tar.gz --files-from -
Run Code Online (Sandbox Code Playgroud)

您可以改为使用该--no-recursion标志tar

find test/ -not -path "*1*" -not -path "*2*" | 
tar -czvf test.tar.gz --no-recursion --files-from - 
Run Code Online (Sandbox Code Playgroud)

结果是:

test/
test/3/
Run Code Online (Sandbox Code Playgroud)

--no-recursion标志特定于 GNU tar。如果您正在使用其他东西,请查阅相应的手册页以查看是否有类似的功能可用。

请注意,您的find命令将排除的文件包含12路径以及目录。


ilk*_*chu 6

使用 GNU tar,您还可以使用--exclude基于名称排除文件的选项。

$ tar --exclude "*1*" --exclude "*2*" -cvf foo.tar  test/
test/
test/3/
Run Code Online (Sandbox Code Playgroud)

还有-Xor --exclude-fromwhich 需要一个文件,从中读取排除模式。


虽然 as find -not -path "*1*",这也将排除名称包含1或的文件2。要仅跳过名称与模式匹配的目录,请使用find -prunetar --no-recursion

$ touch test/3/blah.1
$ find test/ -type d \( -name "*1*" -o -name "*2*" \) -prune -o -print |
   tar cvf test.tar --files-from - --no-recursion
test/
test/3/
test/3/blah.1
Run Code Online (Sandbox Code Playgroud)

(至少 GNU tar 和 FreeBSD tar 有--no-recursion