GNU/Linux >> Belajar Linux >  >> Linux

Bash:Penggunaan Prosedural Find Into Select yang aman-spasi?

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

Terkait:acing -Temukan Arti- Pencarian Kamus!
Linux
  1. Bagaimana Cara Mencatat Setiap Perintah yang Diketik Ke Bash Dan Setiap Operasi File?

  2. Temukan File Log Firefox?

  3. Metode Apa yang Digunakan Unzip Untuk Menemukan Satu File Dalam Arsip?

  1. temukan dan salin file menggunakan Bash

  2. Fungsi Bash untuk menemukan pola pencocokan file terbaru

  3. Ubah ekstensi file secara rekursif di Bash

  1. Cara menggunakan perintah riwayat Bash

  2. Basa'?

  3. Bagaimana cara mengurutkan file ke dalam folder berdasarkan tipe file di bash (dengan perintah 'file')?