当目标目录及其内容时,-name 切换到 GNU 如何找到工作?

当目标目录及其内容时,-name 切换到 GNU 如何找到工作?

我有一个充满应用程序源文件的文件夹,该项目使用 git 进行版本控制,因此有一个.git目录:

├── composer.json
├── .git
│   ├── branches
│   ├── config
│   ├── info
│   ├── logs
│   ├── objects
│   ├── packed-refs
│   └── refs
├── .gitignore
├── Gruntfile.js
├── less
│   ├── framework
│   ├── index.less
│   └── view_specific.less
├── package.json
[...]

我经常需要对所有源文件执行某些操作,同时忽略版本控制文件,即.git目录及其下的所有内容。
我通常使用-not -path选项来find排除目录,例如

find . -not -path "*git*" 

这样做的问题是它太宽泛了,例如它将排除该.gitignore文件以及任何其他包含该文件的文件git其中,例如激荡,逃亡者
我发现findand-name开关似乎-prune确实针对.git目录及其内容:

% find . -name ".git" -prune -o -print | grep git
./.gitignore

但我不明白如何-name匹配文件名。
man find

   -name pattern
      Base  of  file  name (the path with the leading directories removed) matches shell pattern pattern.  

对我来说,这意味着,-name仅当模式与文件名中的最后一段匹配时才匹配,例如-name foo会匹配/dir1/dir2/foo不是 /dir1/dir2/foo/dir3/dir4/some_file 对我来说,重点-path是匹配模式,例如foo与具有路径名的文件,例如/dir1/dir2/foo/dir3/dir4/some_file.
它似乎-name可以匹配文件路径中的任何段 - 不仅仅是最后一个段 - 只要它与斜杠内的段完全匹配?
否则如何-name匹配文件名?

答案1

要忽略.git目录及其下面的所有内容,您需要这样的构造

find . \( -name '.git' -prune \) -o \( -print {or whatever else you want to do} \)

这表明当它找到一个名为它的find文件或目录时.git修剪它的树,而不是沿着那条路进一步下降。其他一切都可以在另一半的范围内进行匹配和处理或者条件构造。

(括号上的反斜杠阻止 shell 处理它们,对于这个简单的示例在技术上是不必要的。我将它们留在里面是为了明确地表明或者构造绑定。)

现在,考虑一下您对名为 的文件夹的担忧foo

例如-name foo会匹配/dir1/dir2/foo但不匹配/dir1/dir2/foo/dir3/dir4/some_file

你是对的,但我认为你错过了推论。到了某个时候find就会达到/dir1/dir2/foo。 will-name foo匹配,因此-prunewill 被调用。如果不先看到它自己find,就无法到达下面。foofoo

因此/dir1/dir2/foo/dir3/dir4/some_file永远无法达到。

检查的初始结果是在某种程度上-name foo匹配/dir1/dir2/foo/dir3/dir4/some_file,但实际上它匹配/dir1/dir2/foo并且放弃了对该树的任何进一步检查。

与仅作为路径的最后一个组成部分-name foo匹配的相比,仅当是完整路径时才会匹配。 (可能会在顶层匹配 a ,但永远无法匹配。)foo-path foofoofind * -path foofoofind . -path foo./foo

答案2

你的理解-name是正确的。它只匹配文件名;通向该文件的路径(包含目录的链)是无关紧要的。

你缺少的是 的效果-prune。对比

find . -name ".git" -o -print 

这意味着“如果它被调用.git,那么什么都不做,否则打印路径并递归到它(如果它是一个目录)”

find . -name ".git" -prune -o -print 

这意味着“如果它被称为.git,那么不要递归它,否则打印路径并递归到它(如果它是目录)”。

相关内容