我需要.git
从我的find
搜索中排除。为了实现这一点,我使用了-path ./.git -prune
开关:
$ find . -path ./.git -prune -o \( -type f -o -type l -o -type d \) | grep '.git'
./.git
但是,即使这会跳过 .git 目录的内容,它也会列出目录本身。当我添加时它起作用-path ./.git -prune -o -print -a
find . -path ./.git -prune -o -print -a \( -type f -o -type l -o -type d \) | grep '.git'
为什么这是必要的。我认为这两个命令应该有相同的输出。第二种语法相当难看。
答案1
我很困惑为什么命令也会打印修剪的目录find
,以及其他一些如何-prune
工作的复杂细节,但能够通过一些示例来弄清楚。
要运行下面的示例,请创建以下目录和文件。
mkdir aa
mkdir bb
touch file1
touch aa/file1
touch bb/file3
要创建此结构:
$ tree
.
├── aa
│ └── file1
├── bb
│ └── file3
└── file1
现在使用 find 来查找名为 的目录aa
。这里没问题。
$ find . -type d -name aa
./aa
查找除aa之外的所有目录,我们得到当前目录.
和./bb
,这也是有道理的。
$ find . -type d ! -name aa
.
./bb
到目前为止一切都很好,但是当我们使用时-prune
, find 返回我们正在修剪的目录,这最初让我感到困惑,因为我期望它返回所有其他目录,而不是正在修剪的目录。
$ find . -type d -name aa -prune
./aa
解释了它返回被修剪的目录的原因,而不是在-prune
手册页的部分中指出蒂莫的回答,但在该EXPRESSIONS
部分中:
如果表达式不包含除 之外的任何操作
-prune
,
这意味着,由于表达式与aa
目录名称匹配,因此表达式将计算为 true 并将被打印,因为 find-print
在整个命令的末尾隐式添加了 a 。-print
但是,如果您自己故意将操作添加-o -print
到末尾,它不会添加:
find . -type d -name aa -prune -o -print
.
./file1
./bb
./bb/file3
这里 find 命令不再添加隐式-print
,因此我们正在修剪 ( ) 的目录aa
将不会被打印。
所以最后,如果我们添加一个子句来搜索文件名模式为 的文件file*
,-o
那么您必须-print
在第二个子句的末尾添加一个,如下所示:
find . \( -type d -name aa -prune \) -o \( -type f -name 'file*' -print \)
./file1
./bb/file3
其工作原理是相同的:如果您不在-print
第二个子句中放置 a,那么由于除了该-prune
操作之外没有其他操作,find 会-print
自动在命令的末尾添加 a,导致该-prune
子句打印修剪的目录:
find . \( \( -type d -name aa -prune \) -o \( -type f -name 'file*' \) \) -print
./aa
./file1
./bb/file3
一般来说,您需要将-print
命令放在第二个子句中。如果您像原始海报一样将其放在中间,它将无法正常工作,因为正在修剪的文件将立即打印,而第二个子句将没有机会选择它想要的文件:
find . \( -type d -name aa -prune -o -print \) -o \( -type f -name 'file*' \)
.
./file1
./bb
./bb/file3
不幸的是,原始发布者将上面的命令放置-print
在错误的位置,从而导致了错误。它可能适用于他的特定情况,但不适用于一般情况。
有成千上万的人难以理解-prune
其工作原理。应更新手册find
页,以防止全世界对此命令产生无休止的混乱。
答案2
页面man
给出find
:
-prune True; if the file is a directory, do not descend into it. If
-depth is given, false; no effect. Because -delete implies
-depth, you cannot usefully use -prune and -delete together.
因此,在第一个示例中,情况并非如此-path ./.git -prune
,因此不会调用默认操作 ( -print
),因此会打印该行。
答案3
从man
页面,
要忽略整个目录树,请使用 -prune 而不是检查树中的每个文件。例如,要跳过目录“src/emacs”及其下的所有文件和目录,并打印找到的其他文件的名称,请执行以下操作:
find . -path ./src/emacs -prune -o -print
所以,也许你可以使用:
find . -path ./.git -prune -o -print
这不会列出.git
目录。
要指定文件名,您可以这样做:
find . -path ./.git -prune , -name filename
请注意,
逗号运算符。
答案4
忽略命令中特定路径的最佳方法是与命令的排除选项一起find
使用,如下所述。我在 /var/www/html 中有文件夹。将排除此处的伦敦和东京文件夹以列出其余文件夹中的所有文件。find
ls
mumbai, dubai,tokyo, delhi, london, rome
ls /var/www/html |grep -v 'london\|tokyo' #ls exclude example is mentioned here.
查找排除提示如下所示:-
find $(ls /var/www/html |grep -v 'london\|tokyo' ) -type f #run above exclude option with find command as mentioned here.