[解決済み] bashのループリストで空白をエスケープするには?
質問
あるディレクトリのすべての子ディレクトリ(ファイルではない)をループするbashシェルスクリプトがあります。 問題は、いくつかのディレクトリ名がスペースを含んでいることです。
ここに私のテストディレクトリのコンテンツがあります。
$ls -F test
Baltimore/ Cherry Hill/ Edison/ New York City/ Philadelphia/ cities.txt
そして、ディレクトリをループするコードです。
for f in `find test/* -type d`; do
echo $f
done
以下はその出力です。
テスト/ボルチモア テスト/チェリー ヒル テスト/エジソン テスト/ニューヨーク ニューヨーク シティ テスト/フィラデルフィア
Cherry HillとNew York Cityは、2つまたは3つの別々の項目として扱われます。
というように、ファイル名を引用してみました。
for f in `find test/* -type d | sed -e 's/^/\"/' | sed -e 's/$/\"/'`; do
echo $f
done
が、無駄である。
何か簡単な方法があるはずだ。
以下の回答は素晴らしいです。 しかし、これをより複雑にするために、私は常にテスト ディレクトリにリストされたディレクトリを使用したいわけではありません。 時々、私は代わりにコマンドライン パラメータとしてディレクトリ名を渡したいのです。
私は、IFS を設定するという Charles の提案を受け、次のようになりました。
dirlist="${@}"
(
[[ -z "$dirlist" ]] && dirlist=`find test -mindepth 1 -type d` && IFS=$'\n'
for d in $dirlist; do
echo $d
done
)
というように、コマンドラインの引数にスペースがない限り(たとえ引数が引用されていても)、これはうまく動作します。 例えば、このようなスクリプトを呼び出すと
test.sh "Cherry Hill" "New York City"
は次のような出力を生成します。
チェリー ヒル 新しい ニューヨーク 都市
解決方法
まず、その方法はやめましょう。最も良い方法は
find -exec
を適切に使用することです。
# this is safe
find test -type d -exec echo '{}' +
もう一つの安全な方法は、NUL終端のリストを使うことです。
-print0
:
# this is safe
while IFS= read -r -d '' n; do
printf '%q\n' "$n"
done < <(find test -mindepth 1 -type d -print0)
findから配列に代入し、後でその配列を渡すこともできます。
# this is safe
declare -a myarray
while IFS= read -r -d '' n; do
myarray+=( "$n" )
done < <(find test -mindepth 1 -type d -print0)
printf '%q\n' "${myarray[@]}" # printf is an example; use it however you want
もしあなたのサイトが
-print0
をサポートしていない場合、その結果は安全ではありません。ファイル名に改行を含むファイルが存在する場合、以下のように動作しません(もちろん、これは合法です)。
# this is unsafe
while IFS= read -r n; do
printf '%q\n' "$n"
done < <(find test -mindepth 1 -type d)
上記のいずれかを使用しない場合、3 番目の方法 (単語分割を行う前にサブプロセスの出力全体を読み込むため、 時間とメモリの使用量の両面で効率的ではありません) は
IFS
変数を使うことです。グロビングをオフにする (
set -f
のようなグロブ文字を含む文字列を防ぐために
[]
,
*
または
?
が展開されないようにします。
# this is unsafe (but less unsafe than it would be without the following precautions)
(
IFS=$'\n' # split only on newlines
set -f # disable globbing
for n in $(find test -mindepth 1 -type d); do
printf '%q\n' "$n"
done
)
最後に、コマンドラインパラメータの場合、シェルがサポートしていれば配列を使うべきです(つまり、ksh、bash、zshです)。
# this is safe
for d in "$@"; do
printf '%s\n' "$d"
done
は分離を維持します。なお、クォート(と
$@
ではなく
$*
のように) を使うことが重要です。配列はグロブ式など他の方法でも入力することができます。
# this is safe
entries=( test/* )
for d in "${entries[@]}"; do
printf '%s\n' "$d"
done
関連
-
[解決済み] Bashスクリプトのソースディレクトリをスクリプト自体から取得するにはどうすればよいですか?
-
[解決済み] Bashシェルスクリプトでディレクトリが存在するかどうかを確認するにはどうすればよいですか?
-
[解決済み] Bashで通常のファイルが存在しないかどうかを判断する方法を教えてください。
-
[解決済み] JavaScriptのオブジェクトをループスルーまたは列挙するにはどうすればよいですか?
-
[解決済み] Bashで文字列変数を連結する方法
-
[解決済み] Bashで文字列が部分文字列を含むかどうかをチェックする方法
-
[解決済み] Bashスクリプトからプログラムが存在するかどうかを確認するにはどうすればよいですか?
-
[解決済み] Bashで文字列をデリミターで分割するには?
-
[解決済み] Bashでコマンドライン引数を解析するには?
-
[解決済み] Bashで文字列の配列をループする?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] シェルプログラミングで「export」は何をするのですか?重複
-
[解決済み] find を使ってサブディレクトリを除外する
-
[解決済み] bash で "set -o nounset" を使用したときに変数が設定されているかどうかをテストする。
-
[解決済み] bashでalt + numericを押すと(arg [numeric])と出ますが、これは何でしょう?
-
[解決済み] Docker: 実行中のDockerコンテナの停止と削除
-
[解決済み] unset の使用と変数への空の設定
-
[解決済み] Bashでディレクトリではなく、ファイルだけをリストアップする方法は?
-
[解決済み] homebrew パッケージがインストールされているかどうかを検出する
-
[解決済み] bash で文字列をエスケープするコマンド
-
[解決済み] MSYSでフォルダを閲覧する