このスクリプトがあります。
#!/bin/bash
function main {
while read -r file; do
do_something "$file"
done <<< $(find . -type f 2>/dev/null)
}
function do_something{
echo file:$@
}
Linuxではうまく機能しますが、Mac(Bashバージョン5.2)では、見つかったすべてのファイルを1つの項目として扱い、改行なしで文字列全体を渡しますdo_something
。
while read -r file; do
echo file:"$file"
done <<< $(find . -type f 2>/dev/null)
MacのBash端末でも直接うまく機能します。それでは何が間違っていますか?
答え1
この文字列演算子がzshからコピーされた以前のバージョンのbashでは、引用符<<< $param$((arith))$(cmdsubst)
なし<<<
の拡張子が-splittingの影響を受け、結果の$IFS
単語が空白に関連付けられ、結果がターゲットの一時ファイルに渡される作成に保存されました。
この問題は4.4で修正されました。バラよりCWRU/変更ログの該当項目:
2015-09-02
redir.c
- write_here_string:ここで文字列文書をトークン化しないでください。 bashのドキュメントでは、bashは何年もこの作業を行ってきましたが、ここで文字列を実装している他のシェルがトークン化を実行していないにもかかわらず、常にこれは起こらないと言います。最終的な効果は、IFS文字シーケンスが空白に縮小されることです。 Clint Hepnerが報告したバグを修正<[Eメール保護]>
しかし、macOSはまだ古代バージョンのbashを使用しています。他の場所に最新のbashをインストールしたかもしれませんが、私が知っている限り、shebangで使用されている/ bin / bashは5.2ではなく3.2.xです。
を参照すると、その特定の問題は解決されますが、ここでの反復結果は間違いなく$(find...)
間違ったアプローチです。find
理由と正しい選択肢を確認してください検索結果を繰り返すのはなぜ悪い習慣ですか?
つまり、bash
ループ(でも利用可能zsh
)を使用する必要がある場合:
while IFS= read -rd '' -u3 file; do
something with "$file"
done 3< <(find . -type f -print0 2> /dev/null)
(プロセスの置き換え、、、、、、-r
kshからコピーされたすべては、-u
2.05b以前-d
または2.05bと同じバージョンで導入されているため、<<<
macosで利用可能でなければなりません/bin/bash
)
macosにはzshがプリインストールされているので、zshに切り替えて次のように書くこともできます。
for file (**/*(ND.)) something with $file
また見なさい: