Bashスクリプトでは、次のことをお勧めします。lsの出力を解析しないでください。
上記のWebページでは、次のコードをお勧めします。
# Good!
for f in *; do
[[ -e $f ]] || continue
...
done
または、ファイル名で配列を入力します。
myfiles=( ~/* )
しかし、例を見て、通常Bourne Shellが引用符で囲まれていない文字列をどのように処理するかを見ると、スペースを含むファイル名にこのコードを使用すると、globがすべての(スペースで区切られた)単語を爆発させるように感じます。 。たとえば、次のディレクトリがある場合
$ ls -1
a file I downloaded from the net.pdf
apple.sh
hello world.txt
私はこれを実行します
for file in *
do printf "%s\n" "$file"
done
引用符で囲まれていない文字列の動作が予想されます。例えば
a
file
I
downloaded
from
the
net.pdf
apple
hello
world
しかし、私が得ることは正しい行動です
a file I downloaded from the net.pdf
apple
hello world
配列に類似
myfiles=( * )
declare -p myfiles
declare -a myfiles='([0]="a file I downloaded from the net.pdf" [1]="apple" [2]="hello world")'
私の質問はこれがなぜですか?
単語分割後のグローバル拡張によるものでしょうか? (この種のファイル操作が正しい出力を生成するためには?)
答え1
トークン化後にファイル名拡張が行われます。
https://www.gnu.org/software/bash/manual/html_node/Shell-Expansions.html#Shell-Expansions
拡張順序は、中かっこ拡張、引数と変数拡張、算術拡張、コマンド置換(左から右へ)です。
答え2
[[ -e $f ]]
特別なケースです。[[
予約語は異なる規則[[
の間で有効です。]]
そのうちの1つは単語分割を行いません。