查找除某些目录之外的所有可执行文件

查找除某些目录之外的所有可执行文件

我正在寻找不在我的$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

假设 GNUfindbashshell(如问题中所使用的),这是一个简短的脚本,可以完成您想要做的事情:

#!/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包含通配字符(这些仍然会出现问题,因为-pathof 的操作数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}\在任何匹配的内容之前添加 a pattern(这里是所有egrep正则表达式运算符)
  • ${(j[|])array}连接数组的元素以|获得/dir|/dir\.2|...正则表达式。

相关内容