如何在Bash的$ PATH上找到文件?

时间:2019-03-27 16:49:47

标签: bash path posix

实用程序s/ # substitute \( # start arg1 [^\"]*\.html # all char before .html without " \) # end of arg1 /javadoc\/\1 # replace with javadoc/arg1 /g # global on whole line 将在路径上找到一个程序,但是任意数据文件呢?

我肯定在搜索错误的东西,但是我找不到用标准实用程序执行此操作的任何方法,因此我想到编写一些Bash脚本来完成此操作。

which环境变量由冒号分隔,但是尝试设置$PATH然后对结果进行迭代对我来说不起作用。这是到目前为止我得到的:

IFS=':'

目前,它仅输出我路径中的第一个条目,而不是全部。

有什么想法吗?如果已经有执行此操作的标准命令,则没有理由编写脚本...

4 个答案:

答案 0 :(得分:3)

这里发生了一些事情:

  1. IFS=':' DIRS=($PATH)

    bash会在设置IFS和DIRS之前扩展变量 ,因此到那时为时已晚。 您需要疯狂的东西

    dirs=()
    while IFS= read -r -d: dir || [ "$dir" ]; do dirs+=("$dir"); done <<<"$PATH"
    

    -不,那是错的。首先,扩展$ PATH变量,然后设置IFS,然后使用IFS拆分DIRS元素,因为它没有被引用。

  1. for d in $DIRS; do echo $d; done

    要遍历数组的所有元素,您需要

    for d in "${dirs[@]}" ...
    

    对于数组,$DIRS等于${DIRS[0]},即第一个条目。

  2. 不要使用ALLCAPS变量名。覆盖关键的系统变量太容易了。

  3. Quote your variables,除非您确切地知道 ,否则,会发生什么。

答案 1 :(得分:2)

使用它,使用bash 参数扩展 anfd find

find ${PATH//:/\/ } -name 'file'

答案 2 :(得分:2)

要使用bash循环在$name上找到名为PATH的文件,

oldIFS=$IFS
IFS=:
for d in $PATH
do
    [ -f "$d/$name" ] && echo "Found $d/$name"
done
IFS=$oldIFS

在许多系统上,例如debian,which只是一个shell脚本,它使用非常相似的循环。看看less /usr/bin/which

答案 3 :(得分:2)

错误与赋值无关,但没有遍历数组。

IFS=: dirs=($PATH)
for dir in "${dirs[@]}"; do
    echo "$dir"
done

为我工作;或更简洁

printf '%s\n' "${dirs[@]}"

就像您发现的一样,$dirs仅返回数组中的第一项。

要遍历这些目录以查找特定文件,请尝试

desired_file_name=$1  # or whatever
for dir in "${dirs[@]}"; do
    test -e "$dir/$desired_file_name" || continue
    echo "$0: found $dir/$desired_file_name" >&2
done

另一种方法是

find "${dirs[@]}" -name "$desired_file_name"

(对于私有变量,您应该使用小写字母,因此我将DIRS更改为dirs。喊叫也对眼睛有益。)