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

问题描述 投票:0回答:4

实用程序which将在路径上找到一个程序,但是任意数据文件呢?

我一定在寻找错误的东西,但我找不到任何方法用标准实用程序来做这个,所以我想写一个小的Bash脚本来做。

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

IFS=':' DIRS=($PATH)
for d in $DIRS; do echo $d; done

此时它只输出我路径中的第一个条目而不是所有条目。

思考?如果已经有一个标准命令执行此操作,则没有理由编写脚本...

bash path posix
4个回答
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 varnames。覆盖关键的系统变量太容易了。
  3. Quote your variables,除非你确切知道如果不这样做会发生什么。

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


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。少喊叫对眼睛也有好处。)


2
投票

使用这个,使用bash参数扩展anfd find

find ${PATH//:/\/ } -name 'file'
© www.soinside.com 2019 - 2024. All rights reserved.