![find:特殊对待斜杠](https://linux22.com/image/137884/find%EF%BC%9A%E7%89%B9%E6%AE%8A%E5%AF%B9%E5%BE%85%E6%96%9C%E6%9D%A0.png)
我想用来find
匹配路径,但我发现了这个:
-path pattern
文件名与 shell 模式匹配。元字符不处理
/' or
.'特别;所以,例如,find . -path "./sr*sc"
./src/misc
将打印名为(如果存在)的目录的条目。
如何使其仅匹配当前目录中的文件?我需要其他工具来完成这项工作吗?
编辑。正如建议的,这里有一些细节。为了完成这项工作,有-maxdepth
可用-regex
的。然而,在实际应用程序中,路径可能是一个变量,而不是一个简单的常量,这样-maxdepth
效果不好,而且-regex
可能看起来有点矫枉过正。所以我想知道是否有一个简单的解决方案可以find
使其尊重斜线。下面是 rsync 文档,描述了它的行为,这与我想要的非常接近。
目前最好的解决方案是使用正则表达式,但如果您知道任何可以使其变得更简单的东西,那将是受欢迎的。
作为我想要的示例,这里是 rsync 模式规则:
'*' 匹配任何路径组件,但它在斜杠处停止。
使用“**”来匹配任何内容,包括斜杠。
答案1
代替使用-regex
。该模式固定在开始和结束处,因此您可能需要.*
在开始和结束处使用。用于替换不匹配的[^/]*/
glob 。例如:*
/
-regex '.*/sr[^/]*sc.*'
有一个 Perl 小脚本查找2perl声称将命令的参数转换find
为等效的 Perl 脚本。显然,它将具有与-path
as相同的模式匹配find
,但您可以编辑它以接受另一个参数,例如-glob
,然后该参数将使用系统调用fnmatch()
来执行您想要的那种通配符。我对我的版本进行了快速修改,find2perl
如本补丁所示:
--- /usr/bin/find2perl 2016-02-04 19:28:48.000000000 +0100
+++ /tmp/find2perl 2018-07-31 20:38:10.034175198 +0200
@@ -58,2 +58,4 @@
$out .= tab . '$File::Find::name =~ /' . fileglob_to_re(shift) . "/s$1";
+ } elsif (/^glob$/) {
+ $out .= tab . 'fnmatch("'.(shift).'", $name, FNM_PATHNAME|FNM_PERIOD)';
} elsif ($_ eq 'perm') {
@@ -236,2 +238,3 @@
use File::Find ();
+use File::FnMatch qw(:fnmatch); # import everything
(开头的行+
显示了我添加的 3 行)。我需要为 Fedora 添加perl-App-find2perl
软件包perl-File-FnMatch
。您需要在您的系统上找到等效项。
然后您可以运行如下命令
/tmp/find2perl . -glob './sr*sc' | perl
答案2
要防止find
递归到子目录,请使用-maxdepth
标志
find -maxdepth 1 -name "sr*sc"
答案3
某些 shell(例如 和)zsh
支持文件名通配模式。默认情况下启用它,而必须使用和启用它。bash
ksh93
**
zsh
bash
shopt -s globstar
ksh93
set -o globstar
这意味着您应该能够执行以下操作:
for pathname in ./src/**/misc/*.c
# process "$pathname" here
done
一些find
类似的测试,例如-type f
,可以很容易地纳入其中:
for pathname in ./src/**/misc/*.c
[ -f "$pathname" ] || continue # will not skip symbolic links to regular files though
# process "$pathname" here
done