パス名拡張を利用してファイル名を変数に割り当てる安定した方法はありますか?
これはうまくいきますが、少し奇妙に見えます。
the_file="$(echo ~/downloads/stack-*-linux-x86_64-static.tar.gz)"
ファイルが存在するとフルパスが割り当てられ$the_file
、そうでなければ偽のglobパターンが発生します。
答え1
ワイルドカードはリストコンテキストでのみ発生するため、次に割り当てる必要があります。大量に変える、、、またはksh93
:bash
zsh
mksh
yash
the_files=(~/downloads/stack-*-linux-x86_64-static.tar.gz)
またはsh
:
set -- ~/downloads/stack-*-linux-x86_64-static.tar.gz
割り当て$1
、$2
...
そして最初の要素を取得します:"${the_files[1]}"
in zsh
or yash
(または$the_files[1]
in zsh
) または"${the_files[0]}"
in ksh
or bash
.
すべての要素について:("${the_files[@]}"
にも$the_files
ありますzsh
)。
$IFS
:("${the_files[*]}"
また)"$the_files"
の最初の文字で連結された要素を結合するために使用されますzsh
。またはzsh
:の文字列に関連付けられています${(j:, :)the_files}
(ここでは、に関連付けられています,
)。
注意することがあります
スカラー変数に代入
the_file=~/downloads/stack-*-linux-x86_64-static.tar.gz
~
拡大するけどいいえ世界的な。ただし、次のように変数を展開するときに引用符を使用することを忘れた場合:
printf '%s\n' $the_file # instead of printf '%s\n' "$the_file"
その後、$the_file
コンテンツを分割してグローバルに展開します。その瞬間これはうまくいくと思うかもしれませんが、実際にはそうではなく、チルダ拡張と組み合わせるとはるかに混乱する可能性があります。
たとえば、$HOME
is/All * Users/me
と$IFS
isがデフォルトに設定されている場合は、現在のディレクトリのすべてのファイル名(拡張子)が$the_file
含まれて印刷され、/All * Users/me/downloads/stack-*-linux-x86_64-static.tar.gz
その後に続きます。printf
/All
*
Users/me/downloads/stack-*-linux-x86_64-static.tar.gz
パターンがどのファイルとも一致しない場合の対処
ではzsh
エラーが発生しますが、他のシェルではパターンは同じままです。最良のシナリオは、パターンがまったく拡張されないことです。
zsh
つまり、N
glob修飾子を使用します。
the_files=(~/downloads/stack-*-linux-x86_64-static.tar.gz(N))
ksh93
glob演算子に~(N)
似た機能があります:
the_files=(~/downloads/~(N)stack-*-linux-x86_64-static.tar.gz)
shopt -s nullglob
他のシェルでは、一部のグローバルオプション(in bash
、set -o nullglob
in)を有効にする必要がありますyash
。