我正在寻找不在我的$PATH
.
目前我正在这样做
find / \( -path "/opt" -prune -o -path "/var" -prune -o -path "/bin" -prune -o -path "/sbin" -prune -o -path "/usr" -prune -o -path "/opt" \) -o -type f -executable -exec file {} \;
我觉得有更好的方法,我尝试使用 for 循环来IFS=:
分离不同的部分,PATH
但无法让它工作。
编辑:我应该指定我不想为此使用脚本。
答案1
假设 GNUfind
和bash
shell(如问题中所使用的),这是一个简短的脚本,可以完成您想要做的事情:
#!/bin/bash
IFS=:
set -f
args=( -false )
for dirpath in $PATH; do
args+=( -o -path "$dirpath" )
done
find / \( \( "${args[@]}" \) -o \
\( -type d \( ! -executable -o ! -readable \) \) \) -prune -o \
-type f -executable -exec file {} +
首先创建数组args
,其中包含动态构造的参数find
。它通过分割冒号的值$PATH
(我们赋予变量的值)来实现这一点IFS
。当我们$PATH
在循环头中使用不带引号的内容时,就会发生拆分。
通常,shell 会对 的分割生成的每个单词调用文件名通配$PATH
,但我使用set -f
关闭文件名通配,以防万一 中的任何目录路径$PATH
包含通配字符(这些仍然会出现问题,因为-path
of 的操作数find
会将它们解释为模式)。
如果我的PATH
变量包含字符串
/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin
然后args
将是以下列表(这里的每一行都是数组中的一个单独元素,这实际上并不是一组中间有换行符的字符串):
-false
-o
-path
/usr/bin
-o
-path
/bin
-o
-path
/usr/sbin
-o
-path
/sbin
-o
-path
/usr/X11R6/bin
-o
-path
/usr/local/bin
-o
-path
/usr/local/sbin
该列表被插入到find
命令调用中,放在括号中。无需-prune
对每个目录重复,因为您只需像我上面那样使用一次即可。
我选择删除任何不可执行或不可读的目录。这应该可以消除您无法访问或列出其内容的目录的许多权限错误。您想find
通过删除该位来简化命令吗,请使用
find / \( "${args[@]}" \) -prune -o \
-type f -executable -exec file {} +
另外,我file
批量运行找到的路径名,而不是每个路径名运行一次。
答案2
有了zsh
,你可以这样做:
set -o extendedglob
LC_ALL=C find / -regextype egrep \
-regex ${(j[|])${(u)path:P}//(#m)[][.\$^*()+{}\\|.]/\\$MATCH} -prune -o \
-type f -executable -exec file {} +
$path
是一个特殊的数组捆绑到$PATH
环境变量。$path:P
获取每个成员的真实路径(绝对、规范、无符号链接)${(u)array}
删除重复项(在规范化之后)${array//(#m)pattern/\\$MATCH}
\
在任何匹配的内容之前添加 apattern
(这里是所有egrep正则表达式运算符)${(j[|])array}
连接数组的元素以|
获得/dir|/dir\.2|...
正则表达式。