find:特殊对待斜杠

find:特殊对待斜杠

我想用来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 脚本。显然,它将具有与-pathas相同的模式匹配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支持文件名通配模式。默认情况下启用它,而必须使用和启用它。bashksh93**zshbashshopt -s globstarksh93set -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

相关内容