Diberikan nama file ini:
$ ls -1
file
file name
otherfile
bash
itu sendiri baik-baik saja dengan spasi putih tertanam:
$ 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
#?
Namun, terkadang saya mungkin tidak ingin bekerja dengan setiap file, atau bahkan secara ketat di $PWD
, di situlah find
masuk. Yang juga menangani spasi putih secara nominal:
$ find -type f -name file*
./file
./file name
./directory/file
./directory/file name
Saya mencoba membuat versi whispace-safe dari scriptlet ini yang akan mengambil output dari find
dan sajikan ke select
:
$ select file in $(find -type f -name file); do echo $file; break; done
1) ./file
2) ./directory/file
Namun, ini meledak dengan spasi putih di nama 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
Biasanya, saya akan menyiasatinya dengan bermain-main dengan IFS
. Namun:
$ 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'
Apa solusinya?
Jawaban yang Diterima:
Jika Anda hanya perlu menangani spasi dan tab (bukan baris baru yang disematkan) maka Anda dapat menggunakan mapfile
(atau sinonimnya, readarray
) untuk membaca ke dalam array mis. diberikan
$ ls -1
file
other file
somefile
lalu
$ 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
Jika Anda melakukannya perlu menangani baris baru, dan bash
. Anda version menyediakan mapfile
yang dibatasi null , maka Anda dapat memodifikasinya menjadi IFS= mapfile -t -d '' files < <(find . -type f -print0)
. Jika tidak, rakit array yang setara dari find
. yang dibatasi null keluaran menggunakan read
lingkaran:
$ 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
opsi telah ditambahkan ke mapfile
di bash
versi 4.4 iirc