次のファイル名が与えられた場合:
$ 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
whspace安全バージョンを作成しようとしています。これスクリプトレットは出力を取得してfind
次にレンダリングします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'
この問題に対する解決策は何ですか?
ベストアンサー1
埋め込み改行文字ではなく、スペースやタブのみを処理する必要がある場合は、次のように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
もしあなたならする改行を処理する必要があり、バージョンが null で区切られた1 をbash
提供する場合は、これを に変更できます。それ以外の場合は、ループを使用してnullで区切られた出力からその配列をアセンブルします。mapfile
IFS= mapfile -t -d '' files < <(find . -type f -print0)
find
read
$ touch $'filename\nwith\nnewlines'
$
$ 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
1 このオプションは-d
バージョン 4.4 iircmapfile
で追加されました。bash