PATHに似た場所のリストからリソースファイルを取得する方法は?

PATHに似た場所のリストからリソースファイルを取得する方法は?

PATH私はposixシェルがコマンド名に基づいてバイナリを検索するのと同じ意味を使用して、特定のファイルの可能な資産ファイルの場所のリストを簡単に検索できるようにしたいと思います。

たとえば、次のようなディレクトリ構造があるとします。

/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 スクリプトや関数でラップする 1 つのアプローチがあります。

$ 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"

明らかに、これらのディレクトリやファイルは私のシステムには存在しないため、実行時に標準出力はありません。

関連情報