实用程序which
将在路径上找到一个程序,但是任意数据文件呢?
我一定在寻找错误的东西,但我找不到任何方法用标准实用程序来做这个,所以我想写一个小的Bash脚本来做。
$PATH
环境变量由冒号分隔,但是尝试设置IFS=':'
然后迭代结果对我来说不起作用。这是我到目前为止所得到的:
IFS=':' DIRS=($PATH)
for d in $DIRS; do echo $d; done
此时它只输出我路径中的第一个条目而不是所有条目。
思考?如果已经有一个标准命令执行此操作,则没有理由编写脚本...
这里发生了一些事情:
IFS=':' DIRS=($PATH)
bash会在设置IFS和DIRS之前扩展变量,所以到那时为时已晚。你需要一些疯狂的东西
dirs=()
while IFS= read -r -d: dir || [ "$dir" ]; do dirs+=("$dir"); done <<<"$PATH"
- 不,这是错的。首先扩展$ PATH变量,然后设置IFS,然后使用IFS拆分DIRS元素,因为它是不加引号的。
for d in $DIRS; do echo $d; done
要迭代遍历数组的所有元素,您需要
for d in "${dirs[@]}" ...
对于数组,$DIRS
等于${DIRS[0]}
,即第一个条目。要使用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
。
错误不在于赋值,而是在数组上没有循环。
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
。少喊叫对眼睛也有好处。)
使用这个,使用bash参数扩展anfd find
:
find ${PATH//:/\/ } -name 'file'