以下の関数を使用してすべてのサブディレクトリを印刷しようとしていますが、何らかの理由でファイル名にスペース( "")が含まれている場合、名前はecho
2つの部分に分割されます。例は次のとおりです。
私のディレクトリにはというディレクトリが含まれていますr1 August.request
。
出力は次のとおりです
r1
August.request
私が探しています
r1 August.request
これは私のスクリプトです。
#!/bin/bash
function ScanFile {
for file in `ls` ; do
if [[ -d "$file" ]] ; then
cd "$file"
ScanFile
cd ..
else
echo "$file"
fi
done
}
ScanFile
答え1
SH互換シェルにはいわゆるIFS変数があります。 IFS代表内部フィールド区切り記号。この変数は、シェルがパラメータ境界(位置パラメータの境界など)を検出する方法を制御します。
基本的には次のようになります。
set IFS=$' \t\n'
これは、入力をスペース、タブ、および改行区切りトークンに分割することを意味します。
ファイルはスペースで構成されています。この試み:
OLD_IF="$IFS"
IFS=$'\t\n'
for file in `ls -1` ; do
# Content of your loop
done
IFS="$OLD_IFS"
ここで重要なのは、以前のIFS値を保存して復元することです。
編集:ls -1
1行に1つのファイルのリストを追加して、上記の操作を実行します。
答え2
バッシュから:
shopt -s globstar
ls -1d **/
答え3
関数解析の引用符なしの出力ですls
。これはシェルですls
。
代わりに:
dirwalk () {
indent=${1:-0}
for name in *; do
[ ! -e "$name" ] && continue
if [ -d "$name" ]; then
printf '%*sDir: "%s"\n' "$indent" "" "$name"
( cd "$name" && dirwalk "$(( indent + 4 ))" )
else
printf '%*sFile: "%s"\n' "$indent" "" "$name"
fi
done
}
またはカラフルなインデントなし
dirwalk () {
for name in *; do
[ ! -e "$name" ] && continue
if [ -d "$name" ]; then
printf 'Dir: "%s"\n' "$name"
( cd "$name" && dirwalk )
else
printf 'File: "%s"\n' "$name"
fi
done
}
*
代わりに出力を使用すると、ファイルls
名にスペースが含まれていても、現在のディレクトリを繰り返すために正しく区切られたファイル名のリストが生成されます。
テストは、-e
繰り返す項目が実際に存在することを確認することです。空のディレクトリを入力すると、拡張されずに*
そのまま残ります*
。で一致しないパターンが空になるようにシェルオプションをbash
設定できます。nullglob
shopt -s nullglob
サブシェル(括弧内)でこれを使用すると、以前のディレクトリに戻ることをcd
覚えておく必要はありません。cd ..
外部環境は内部環境の影響を受けませ( ... )
ん。cd
printf
代わりに、echo
出力形式をよりよく制御できます。また見てください」なぜprintfがechoより優れているのですか?」。