![如何在类似 PATH 的位置列表中搜索资源文件?](https://linux22.com/image/157904/%E5%A6%82%E4%BD%95%E5%9C%A8%E7%B1%BB%E4%BC%BC%20PATH%20%E7%9A%84%E4%BD%8D%E7%BD%AE%E5%88%97%E8%A1%A8%E4%B8%AD%E6%90%9C%E7%B4%A2%E8%B5%84%E6%BA%90%E6%96%87%E4%BB%B6%EF%BC%9F.png)
我希望能够使用与 posix shell 基于PATH
命令名称搜索二进制文件的方式类似的语义,轻松地搜索特定文件的可能资产文件位置列表。
例如,如果我有这样的目录结构:
/usr/foo/assets
+- sounds
| +- ding.ogg
| +- dong.ogg
+- images
+- foo.png
/usr/local/foo/assets
+- sounds
| +- ding.flac # better ding
+- images
+- bar.png
我希望能够定义某种搜索路径;例如这个,还包括用户自己的.local
,然后在我自己的资产文件夹之后回退到 freedesktop 默认声音:
FOO_SOUNDS_PATH=$HOME/.local/foo/assets/sounds:/usr/local/foo/assets/sounds:/usr/foo/assets/sounds:/usr/share/sounds/freedesktop/stereo
最终结果是我希望能够仅使用基本名称来引用文件,而不是自己手动确定完整路径,这将允许我编写类似于以下内容的内容:
#!/bin/bash
play_sound(){
paplay $(find_on_path --ext="ogg,wav,mp3,flac" --path="$FOO_SOUNDS_PATH" "$1")
}
play_sound ding # play /usr/local/foo/assets/sounds/ding.flac
play_sound dong # play /usr/foo/assets/sounds/dong.ogg
# fallback to freedesktop system 'complete' sound:
play_sound complete # play /usr/share/sounds/freedesktop/stereo/complete.ogg
请注意,我使用的是声音文件,因为这是一个方便的示例,但我真正对更通用的技术感兴趣,而不是特别对如何播放系统声音感兴趣。
是否有一种简单的方法可以将这些相同的$PATH
语义重用于其他类型的资源,如果可以,如何实现?如果不是,我应该如何做呢?
答案1
好吧,这是一种方法;您也许可以将这些想法包装到 bash 脚本或函数中:
$ FOO_SOUNDS_PATH=$HOME/.local/foo/assets/sounds:/usr/local/foo/assets/sounds:/usr/foo/assets/sounds:/usr/share/sounds/freedesktop/stereo
$ IFS=':' read -r -a array <<< "$FOO_SOUNDS_PATH" # IFS splits path into array var by ':'
$ echo "${array[@]}"
$ /home/sparrow/.local/foo/assets/sounds /usr/local/foo/assets/sounds /usr/foo/assets/sounds /usr/share/sounds/freedesktop/stereo
这意味着你可以推断:
$ for i in "${array[@]}"; do find $i -type f -name *.ogg -or -name *.wav -or -name *.mp3 -or -name *.flac -printf "%f\n"; done
这将为您提供所有相关的声音文件...您必须编写其余部分的脚本,以便将这些文件保存为变量以便根据命令播放它们。我希望我至少为您指明了正确的方向!
答案2
尝试一些变体:
$ cat tst.sh
#!/bin/env bash
assPath='/foo:/bar/whatever:/somewhere/else'
assFind() {
local tgt="$1" dir assArr
IFS=':' read -r -a assArr <<< "$assPath"
for dir in "${assArr[@]}"; do
printf 'Searching "%s"\n' "$dir" >&2
if [[ -e "${dir}/${tgt}" ]]; then
printf '%s/%s\n' "$dir" "$tgt"
return 0
fi
done
return 1
}
assFind 'ding.ogg'
$ ./tst.sh
Searching "/foo"
Searching "/bar/whatever"
Searching "/somewhere/else"
显然,我的系统上并没有这些目录或文件,因此当我运行它时没有标准输出。