パス名の展開を利用して変数にファイル名を割り当てる信頼できる方法はありますか?
これは機能しますが、怪しげに見えます。
the_file="$(echo ~/downloads/stack-*-linux-x86_64-static.tar.gz)"
ファイルが存在する場合、その完全パスが$the_file
に割り当てられます。それ以外の場合は、偽のglobパターンが発生します。
グロッビングはリストコンテキストでのみ発生するため、array変数に割り当てる必要があります。 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
またはyash
(または単に$the_files[1]
in zsh
)または"${the_files[0]}"
in ksh
またはbash
。
すべての要素:"${the_files[@]}"
(zsh
内の$the_files
も)。
$IFS
の最初の文字に結合された要素の連結については、"${the_files[*]}"
(_zsh
を含む"$the_files"
も)。または、zsh
:${(j:, :)the_files}
の任意の文字列と結合します(ここでは,
と結合します)。
the_file=~/downloads/stack-*-linux-x86_64-static.tar.gz
~
は展開されますが、notグロブです。ただし、次のように変数を展開するときに引用符を使用するのを忘れた場合:
printf '%s\n' $the_file # instead of printf '%s\n' "$the_file"
次に、$the_file
のコンテンツはsplit + globの対象となり、その時点で展開されますこれにより、実際には機能しないと考えられますチルド拡張と組み合わせるとさらに面倒になります。
たとえば、$HOME
が/All * Users/me
であり、$IFS
がデフォルト値に設定されている場合、$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
グロブ修飾子を使用できます。
the_files=(~/downloads/stack-*-linux-x86_64-static.tar.gz(N))
ksh93
には、~(N)
グロブ演算子を使用した同様の機能があります。
the_files=(~/downloads/~(N)stack-*-linux-x86_64-static.tar.gz)
他のシェルでは、いくつかのグローバルオプションをオンにする必要があります(bash
のshopt -s nullglob
、yash
のset -o nullglob
)。