我有一组相当复杂的文件需要查找和反应(例如复制到文本文件的路径):
例如:
find / \( -iname "*ssh*" -or -iname "*scp*" \) \( -not -path -"/run" -not -path "/rw/*" -and -not -path "/home/*" -and -not -path "*/qml/*" \) >> ~/files.txt
在这里我想找到与“ssh”和“scp”相关但不在 /run 或 /rw 目录中的所有文件或文件夹。
我将为此添加更多条件,但命令太长了。我怎样才能用正则表达式做到这一点?
答案1
最好是根本不要下降到您想要排除的那些目录中,而不是在事后使用以下命令过滤掉其中的文件! -path <pattern>
:
LC_ALL=C find / \
'(' \
-path /run -o -path /rw -o -path /home -o -path '*/qml' \
')' -prune -o '(' \
-name '*[sS][hH][hH]*' -o -name '*[sS][cC][pP]*' \
')' -print
这里使用POSIXfind
语法。对于 GNU find
,这可能是:
LC_ALL=C find / -regextype posix-extended \
-regex '/home|/rw|.*/qml' -prune -o \
-iregex '.*s(cp|sh)[^/]*' -print
使用 BSD find
,您只需使用-E
类似 ingrep
或sed
即可获取 POSIX ERE:
LC_ALL=C find -E / \
-regex '/home|/rw|.*/qml' -prune -o \
-iregex '.*s(cp|sh)[^/]*' -print
答案2
这是一个带有换行符的版本,更容易阅读,并且修复了一些拼写错误。我假设 GNU 查找,但稍作修改也适用于大多数 BSD 查找。
find / \
\( -iname "*ssh*" -or -iname "*scp*" \) \
\( -not -path "/run/*" \
-not -path "/rw/*" \
-not -path "/home/*" \
-not -path "*/qml/*" \) \
>> ~/files.txt
现在为了简化一点,-iname "*ssh*" -or -iname "*scp*"
可以写成正则表达式,例如
find ... \
-regextype posix-extended \
-iregex '.*(ssh|scp)[^/]*' \
...
现在您可以更轻松地添加额外的名称,例如(ssh|scp|rsync|...)
.
这些-not -path
测试可以组合成一个正则表达式,如下所示:
find ... \
-not -regex '(/run|/rw|/home|.*/qml)/.*'
但find
仍然会浪费大量时间探索这些目录,除非您使用-prune
:
find / \
-regextype posix-extended \
-not \( -regex '(/run|/rw|/home|.*/qml)/.*' -prune \) \
-iregex '.*(ssh|scp)[^/]*' \
>> ~/files.txt