find 命令不能排除确切的正则表达式
find command can't exclude the exact regex
我有以下脚本:
#!/bin/bash
arg=
exclude='(/etc/alternatives/(awk|vim)|/usr/sbin/poweroff)$'
find $arg -type f,l,c,b -regextype posix-extended -not -regex "${exclude}" -print
我没有在每个文件的开头使用 ^
,因此它可以以任何内容开头。但是我在每个文件的末尾都使用了$
。
因此,当我 运行 脚本以这种方式正常工作时:
$ sudo bash script.sh /etc/ | grep awk
/etc/alternatives/nawk
/etc/alternatives/nawk.1.gz
/etc/alternatives/awk.1.gz
但是当我这样做时是错误的:
$ sudo cp -rv /etc/ /tmp/
$ sudo bash script.sh /tmp/etc/ | grep awk
/tmp/etc/alternatives/awk
/tmp/etc/alternatives/nawk
/tmp/etc/alternatives/nawk.1.gz
/tmp/etc/alternatives/awk.1.gz
这里您看到文件 /tmp/etc/alternatives/awk
由于缺少 ^
符号而不应在结果中传递。
更新
这个模式很好用,但我想使用上面的模式:
find $arg -type f,l,c,b | grep -Ev "${exclude}"
据我所知,-regex
测试是特定于 GNU 的 find
实现的功能;它不是由 POSIX 定义的。 GNU 的实现无论如何几乎肯定是您会在您最喜欢的 Linux 发行版中找到的那个。 Its manual 有话要说:
Test: -regex expr
Test: -iregex expr
True if the entire file
name matches regular expression expr. This is a match on the whole
path, not a search. [...]
(强调)。也就是说,即使在模式中没有明确的锚点,测试也总是像正则表达式锚定到行的开始端一样执行。您可以通过在正则表达式前添加前缀和/或后缀 .*
来解决这个问题。
对于您的示例,可能如下所示:
exclude='.*(/etc/alternatives/(awk|vim)|/usr/sbin/poweroff)'
我省略了不需要的尾随锚点,因为这对我来说似乎更清楚,但如果你想保留它,那就这样做——它没有害处。
我有以下脚本:
#!/bin/bash
arg=
exclude='(/etc/alternatives/(awk|vim)|/usr/sbin/poweroff)$'
find $arg -type f,l,c,b -regextype posix-extended -not -regex "${exclude}" -print
我没有在每个文件的开头使用 ^
,因此它可以以任何内容开头。但是我在每个文件的末尾都使用了$
。
因此,当我 运行 脚本以这种方式正常工作时:
$ sudo bash script.sh /etc/ | grep awk
/etc/alternatives/nawk
/etc/alternatives/nawk.1.gz
/etc/alternatives/awk.1.gz
但是当我这样做时是错误的:
$ sudo cp -rv /etc/ /tmp/
$ sudo bash script.sh /tmp/etc/ | grep awk
/tmp/etc/alternatives/awk
/tmp/etc/alternatives/nawk
/tmp/etc/alternatives/nawk.1.gz
/tmp/etc/alternatives/awk.1.gz
这里您看到文件 /tmp/etc/alternatives/awk
由于缺少 ^
符号而不应在结果中传递。
更新
这个模式很好用,但我想使用上面的模式:
find $arg -type f,l,c,b | grep -Ev "${exclude}"
据我所知,-regex
测试是特定于 GNU 的 find
实现的功能;它不是由 POSIX 定义的。 GNU 的实现无论如何几乎肯定是您会在您最喜欢的 Linux 发行版中找到的那个。 Its manual 有话要说:
Test: -regex expr
Test: -iregex expr
True if the entire file name matches regular expression expr. This is a match on the whole path, not a search. [...]
(强调)。也就是说,即使在模式中没有明确的锚点,测试也总是像正则表达式锚定到行的开始端一样执行。您可以通过在正则表达式前添加前缀和/或后缀 .*
来解决这个问题。
对于您的示例,可能如下所示:
exclude='.*(/etc/alternatives/(awk|vim)|/usr/sbin/poweroff)'
我省略了不需要的尾随锚点,因为这对我来说似乎更清楚,但如果你想保留它,那就这样做——它没有害处。