次のファイル名を指定します:
$ ls -1
file
file name
otherfile
bash
埋め込まれた空白でそれ自体は完全にうまく機能します:
$ for file in *; do echo "$file"; done
file
file name
otherfile
$ select file in *; do echo "$file"; done
1) file
2) file name
3) otherfile
#?
ただし、すべてのファイルで作業したくない場合や、厳密に$PWD
で作業したくない場合もあります。 、ここでfind
入ってくる。これは名目上空白も処理する:
$ find -type f -name file*
./file
./file name
./directory/file
./directory/file name
find
の出力を取得するこのスクリプトレットのwhispace-safeバージョンを作成しようとしています select
に表示します :
$ select file in $(find -type f -name file); do echo $file; break; done
1) ./file
2) ./directory/file
ただし、これはファイル名の空白で爆発します:
$ select file in $(find -type f -name file*); do echo $file; break; done
1) ./file 3) name 5) ./directory/file
2) ./file 4) ./directory/file 6) name
通常、私はIFS
をいじってこれを回避します 。ただし:
$ IFS=$'n' select file in $(find -type f -name file*); do echo $file; break; done
-bash: syntax error near unexpected token `do'
$ IFS='n' select file in $(find -type f -name file*); do echo $file; break; done
-bash: syntax error near unexpected token `do'
これに対する解決策は何ですか?
承認された回答:
スペースとタブ(埋め込まれた改行ではない)のみを処理する必要がある場合は、mapfile
を使用できます。 (またはその同義語、readarray
)配列に読み込む(例:与えられた
$ ls -1
file
other file
somefile
次に
$ IFS= mapfile -t files < <(find . -type f)
$ select f in "${files[@]}"; do ls "$f"; break; done
1) ./file
2) ./somefile
3) ./other file
#? 3
./other file
行う場合 改行とbash
を処理する必要があります versionは、nullで区切られたmapfile
を提供します 、次にそれをIFS= mapfile -t -d '' files < <(find . -type f -print0)
に変更できます。 。それ以外の場合は、nullで区切られたfind
から同等の配列をアセンブルします read
を使用した出力 ループ:
$ touch $'filenamenwithnnewlines'
$
$ files=()
$ while IFS= read -r -d '' f; do files+=("$f"); done < <(find . -type f -print0)
$
$ select f in "${files[@]}"; do ls "$f"; break; done
1) ./file
2) ./somefile
3) ./other file
4) ./filename
with
newlines
#? 4
./filename?with?newlines
-d
オプションがmapfile
に追加されました bash
で バージョン4.4iirc