如何在类似 PATH 的位置列表中搜索资源文件?

如何在类似 PATH 的位置列表中搜索资源文件?

我希望能够使用与 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"

显然,我的系统上并没有这些目录或文件,因此当我运行它时没有标准输出。

相关内容