der*_*dji 207 regex shell find manual
我不太明白"男人发现"给出的例子,有人能给我一些例子和解释吗?我可以在其中组合正则表达式吗?
更详细的问题是这样的:写一个shell脚本,changeall,它有一个像"changeall [-r | -R]"string1""string2"这样的接口.它将找到后缀为.h,.C的所有文件,.cc或.cpp并将所有出现的"string1"更改为"string2".- r是仅保留当前目录或包含subdir的选项.注意:1)对于非递归情况,不允许"ls" ,我们只能使用'find'和'sed'.2)我试过'find -depth'但它不受支持.这就是为什么我想知道'-prune'是否可以帮助,但是不明白'男人发现'.
EDIT2:我正在做作业,我没有详细提问,因为我想自己完成.既然我已经完成并把它交给我,现在我可以陈述整个问题.此外,我设法在不使用-prune的情况下完成了作业,但无论如何都想学习它.
Lau*_*ves 418
我发现令人困惑的事情-prune
是它是一个动作(比如-print
),而不是一个测试(比如-name
).它改变了"待办事项"列表,但总是返回true.
使用的一般模式-prune
是:
find [path] [conditions to prune] -prune -o \
[your usual conditions] [actions to perform]
Run Code Online (Sandbox Code Playgroud)
你几乎总是想要-o
紧接着-prune
,因为测试的第一部分(包括-prune
)将为你真正想要的东西返回false(即:你不想修剪掉的东西).
这是一个例子:
find . -name .snapshot -prune -o -name '*.foo' -print
Run Code Online (Sandbox Code Playgroud)
这将找到不在".snapshot"目录下的"*.foo"文件.在这个例子中,-name .snapshot
是"你想要修剪的东西的测试",并且[conditions to prune]
是"你通常在路径之后放置的东西".
重要说明:
如果你想要做的就是打印结果,你可能会习惯于忽略这个-name '*.foo' -print
动作.您通常不希望在使用时这样做[your usual conditions]
.
如果除了(具有讽刺意味)最后没有其他操作,则find的默认行为是"和" 整个表达式.这意味着写下这个:[actions to perform]
-print
find . -name .snapshot -prune -o -name '*.foo' # DON'T DO THIS
Run Code Online (Sandbox Code Playgroud)
相当于写这个:
find . \( -name .snapshot -prune -o -name '*.foo' \) -print # DON'T DO THIS
Run Code Online (Sandbox Code Playgroud)
这意味着它还会打印出你正在修剪的目录的名称,这通常不是你想要的.相反,最好明确指定-prune
动作,如果这是你想要的:
find . -name .snapshot -prune -o -name '*.foo' -print # DO THIS
Run Code Online (Sandbox Code Playgroud)如果您的"通常条件"碰巧匹配与您的剪枝条件匹配的文件,那么这些文件将不会包含在输出中.解决此问题的方法是-print
在剪枝条件中添加谓词.
例如,假设我们想要删除任何以某个开头的目录-prune
(这无疑是有点人为的 - 通常你只需要删除完全 命名的东西-print
),但除此之外想要查看所有文件,包括像-type d
.你可以试试这个:
find . -name '.git*' -prune -o -type f -print # DON'T DO THIS
Run Code Online (Sandbox Code Playgroud)
这不包括.git
在输出中.这是固定版本:
find . -name '.git*' -type d -prune -o -type f -print # DO THIS
Run Code Online (Sandbox Code Playgroud)额外提示:如果您使用的是GNU版本.git
,则texinfo页面的.gitignore
解释比其联机帮助页更详细(大多数GNU实用程序都是如此).
Pau*_*ce. 26
请注意,-prune不会像某些人所说的那样阻止降级到任何目录.它可以防止降级到与其应用的测试匹配的目录.也许一些例子会有所帮助(请参阅正则表达式示例的底部).对不起,这是如此冗长.
$ find . -printf "%y %p\n" # print the file type the first time FYI
d .
f ./test
d ./dir1
d ./dir1/test
f ./dir1/test/file
f ./dir1/test/test
d ./dir1/scripts
f ./dir1/scripts/myscript.pl
f ./dir1/scripts/myscript.sh
f ./dir1/scripts/myscript.py
d ./dir2
d ./dir2/test
f ./dir2/test/file
f ./dir2/test/myscript.pl
f ./dir2/test/myscript.sh
$ find . -name test
./test
./dir1/test
./dir1/test/test
./dir2/test
$ find . -prune
.
$ find . -name test -prune
./test
./dir1/test
./dir2/test
$ find . -name test -prune -o -print
.
./dir1
./dir1/scripts
./dir1/scripts/myscript.pl
./dir1/scripts/myscript.sh
./dir1/scripts/myscript.py
./dir2
$ find . -regex ".*/my.*p.$"
./dir1/scripts/myscript.pl
./dir1/scripts/myscript.py
./dir2/test/myscript.pl
$ find . -name test -prune -regex ".*/my.*p.$"
(no results)
$ find . -name test -prune -o -regex ".*/my.*p.$"
./test
./dir1/test
./dir1/scripts/myscript.pl
./dir1/scripts/myscript.py
./dir2/test
$ find . -regex ".*/my.*p.$" -a -not -regex ".*test.*"
./dir1/scripts/myscript.pl
./dir1/scripts/myscript.py
$ find . -not -regex ".*test.*" .
./dir1
./dir1/scripts
./dir1/scripts/myscript.pl
./dir1/scripts/myscript.sh
./dir1/scripts/myscript.py
./dir2
Run Code Online (Sandbox Code Playgroud)
Ami*_*itP 25
通常我们在linux中做本地的方式和我们的思维方式是从左到右.
所以你会先写下你想要的东西:
find / -name "*.php"
Run Code Online (Sandbox Code Playgroud)
然后你可能点击进入并意识到你从你不希望的目录中获取太多文件.我们排除/ media以避免搜索已安装的驱动器.
您现在应该将以下命令附加到上一个命令:
-print -o -path '/media' -prune
Run Code Online (Sandbox Code Playgroud)
所以最后的命令是:
find / -name "*.php" -print -o -path '/media' -prune
Run Code Online (Sandbox Code Playgroud)
............... | <---包括---> | .................... | < - --------排除---------> |
我认为这种结构更容易,并与正确的方法相关联
crw*_*crw 10
添加其他答案中给出的建议(我没有代表创建回复)...
当-prune
与其他表达式组合时,根据使用的其他表达式,行为存在细微差别.
@Laurence Gonsalves的例子会找到不在".snapshot"目录下的"*.foo"文件: -
find . -name .snapshot -prune -o -name '*.foo' -print
Run Code Online (Sandbox Code Playgroud)
但是,这个略有不同的简写,也许是在不经意间,也会列出.snapshot
目录(以及任何嵌套的.snapshot目录): -
find . -name .snapshot -prune -o -name '*.foo'
Run Code Online (Sandbox Code Playgroud)
原因是(根据我系统的联机帮助页): -
如果给定的表达式不包含任何主要的-exec,-ls,-ok或-print,则给定的表达式将被有效替换为:
(given_expression)-print
也就是说,第二个例子相当于输入以下内容,从而修改术语的分组: -
find . \( -name .snapshot -prune -o -name '*.foo' \) -print
Run Code Online (Sandbox Code Playgroud)
这至少在Solaris 5.10上已经出现过.使用各种口味的*nix大约10年后,我最近才搜索出这种情况发生的原因.
我不是这方面的专家(这个页面和http://mywiki.wooledge.org/UsingFind非常有帮助)
刚刚注意到-path
的是完全匹配紧随其后的字符串/路径的find
路径(.
在这些示例中),其中 as-name
匹配所有基本名称。
find . -path ./.git -prune -o -name file -print
Run Code Online (Sandbox Code Playgroud)
阻止当前目录中的 .git 目录(如您在 中的发现.
)
find . -name .git -prune -o -name file -print
Run Code Online (Sandbox Code Playgroud)
递归地阻止所有 .git 子目录。
注意这./
一点非常重要!! -path
必须匹配锚定到的路径.
或 find 之后出现的任何内容,如果您得到没有它的匹配项(来自 or ' -o
' 的另一侧),则可能没有被修剪!我天真地没有意识到这一点,当你不想修剪具有相同基本名称的所有子目录时,它让我使用 -path ,这很棒:D