如何使用查找工具在系统路径($PATH)中查找文件?或者,如何指定查找的起始点目录作为表达式?

如何使用查找工具在系统路径($PATH)中查找文件?或者,如何指定查找的起始点目录作为表达式?

例如,我想在属于系统 $PATH 的所有目录中查找引用特定二进制文件的所有符号链接。这可以通过手动指定所有目录来成功实现:

sudo find ~/bin /home/samokat/.local/bin /home/samokat/bin /usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin /snap/bin -lname /opt/openoffice4/program/soffice

但是当我尝试使用带有 $PATH 扩展的命令时:

sudo find `echo $PATH | tr ':' ' '` -lname /opt/openoffice4/program/soffice

我得到错误和结果:

find: ‘~/bin’: No such file or directory
/usr/bin/soffice.link-to-openoffice-bak
echo $PATH | tr ':' ' '

输出正确路径:

~/bin /home/samokat/.local/bin /home/samokat/bin /usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin /snap/bin

以下也不起作用:

sudo find `echo $PATH | tr ':' ' ' | xargs` -lname /opt/openoffice4/program/soffice
sudo find { `echo $PATH | tr ':' ' ' | xargs` } -lname /opt/openoffice4/program/soffice
sudo find eval "echo $PATH | tr ':' ' ' | xargs" -lname /opt/openoffice4/program/soffice
echo $PATH | tr ':' ' ' | xargs | sudo find -lname /opt/openoffice4/program/soffice  # runs some long computation

如何将starting point目录作为可计算参数传递给find?这可能吗?

答案1

无需使用sudo,因为您$PATH必须包含您已经可以访问的目录。

该字符是Shell 和其他 shell 的~主目录的内置快捷方式。bash但它的评估还不够晚,您无法在示例中使用它。 (它也不会在带引号的表达式中求值。)

当您设置时$PATH,不要使用类似的东西,而是PATH=~/bin:$PATH考虑使用更明确的替代方案PATH="$HOME/bin:$PATH"

对于某些代码,这里有一个可以处理$PATH目录名称中空格的替代解决方案:

( IFS=:; for p in $PATH; do [ -d "$p" ] && find "$p" -maxdepth 1 -lname '/opt/openoffice4/program/soffice'; done )

更具可读性,

(
    IFS=:
    for p in $PATH
    do
        [ -d "$p" ] && find "$p" -maxdepth 1 -lname '/opt/openoffice4/program/soffice'
    done
)

答案2

$PATH确实包含~/bin字面意思,因此它只会在当前工作目录中bin名为字面意思的目录的子目录中找到可执行文件~,就像您运行mkdir -p '~/bin'.

~/bin是假的,应该被删除。

如果你运行:

PATH=~/bin:$PATH

如果~没有引用,那么您会发现printf '%s\n' "$PATH"输出:

/home/you/bin:~/bin:/home/samokat/.local/bin:/home/samokat/bin:...

~/bin将被正确地扩展到bin您的主目录中,然后是~/bin已经存在的虚假文件和您的PATH.

但假设you实际上是samokat,这意味着该目录将出现两次,$PATH其中之一是多余的。

$PATH,修复到 的find所有目录组件中的文件后$PATH,您需要的一切bash

(IFS=:; set -o noglob; find -H $PATH -lname /opt/openoffice4/program/soffice)

特殊参数$IFS决定如何拆分未加引号的参数扩展。默认情况下,$IFS包含空格字符(以及换行符和制表符),这解释了为什么将 s 更改:有效,但最好设置IFS为正确的值。另请注意set -o noglob禁用其他不加引号的参数扩展的副作用。

另请注意,-H如果没有它,find则不会查看实际上是目录符号链接的目录。

或者,如果您可以切换到与数组绑定的zsh位置(如 中),那么它只是:$PATH$pathcsh

find -H $path -lname /opt/openoffice4/program/soffice

在 中zsh,您还可以使用 glob 代替find.

例如:

print -rC1 -- $^path/*(N@e['[[ $REPLY:P = /opt/openoffice4/program/soffice ]]'])

print raw on olumn 实际ath为 的每个组件内的1 C符号链接 () 的路径。@$pathP/opt/openoffice4/program/soffice

相关内容