Saya mencoba membuat array di bash dari nama file dari kamera saya:
FILES=(2011-09-04 21.43.02.jpg
2011-09-05 10.23.14.jpg
2011-09-09 12.31.16.jpg
2011-09-11 08.43.12.jpg)
Seperti yang Anda lihat, ada ruang di tengah setiap nama file.
Saya sudah mencoba membungkus setiap nama dengan tanda kutip, dan melarikan diri dari ruang dengan backslash, tidak ada yang berhasil.
Ketika saya mencoba mengakses elemen array, itu terus memperlakukan ruang sebagai elemen pendahulunya.
Bagaimana saya bisa menangkap nama file dengan benar dengan spasi di dalam nama?
FILES[0] = ...
? (Sunting: Saya baru saja melakukannya; tidak berfungsi. Menarik).find . -maxdepth 1 -type f -iname \*.$1 -printf '%f\n'
); untuk elemen dalam $ {array [@]}; lakukan echo $ element; selesaiJawaban:
Saya pikir masalahnya mungkin sebagian dengan bagaimana Anda mengakses elemen. Jika saya melakukan yang sederhana
for elem in $FILES
, saya mengalami masalah yang sama seperti Anda. Namun, jika saya mengakses array melalui indeksnya, seperti itu, ia berfungsi jika saya menambahkan elemen secara numerik atau dengan escapes:Salah satu dari deklarasi ini
$FILES
harus bekerja:atau
atau
sumber
echo "${FILES[$i]}"
). Tidak masalah untukecho
, tetapi akan untuk apa pun yang menggunakannya sebagai nama file.for f in "${FILES[@]}"
.#
simbol tajam ( ) dalamfor ((i = 0; i < ${#FILES[@]}; i++))
pernyataan?Pasti ada yang salah dengan cara Anda mengakses item array. Begini cara melakukannya:
Dari halaman bash :
Tentu saja, Anda juga harus menggunakan tanda kutip ganda ketika mengakses satu anggota
sumber
expands to a single word with the value of each array member separated by the first character of the IFS special variable
for elem in "${files[@]}"
sementara mereka memilikifor elem in ${files[@]}
- sehingga ruang membingungkan ekspansi dan untuk mencoba berjalan pada kata-kata individual.Anda perlu menggunakan IFS untuk menghentikan ruang sebagai pembatas elemen.
Jika Anda ingin memisahkan berdasarkan. maka lakukan saja IFS = "." Semoga ini bisa membantu Anda :)
sumber
IFS=""
sebelum konstruksi array .Saya setuju dengan orang lain bahwa kemungkinan Anda mengakses elemen yang menjadi masalahnya. Mengutip nama file dalam penugasan array sudah benar:
Menggunakan tanda kutip ganda di sekitar array mana pun dari bentuk
"${FILES[@]}"
membagi array menjadi satu kata per elemen array. Tidak ada pemisahan kata selain itu.Menggunakan
"${FILES[*]}"
juga memiliki arti khusus, tetapi ia menggabungkan elemen array dengan karakter pertama $ IFS, menghasilkan satu kata, yang mungkin bukan yang Anda inginkan.Menggunakan bare
${array[@]}
atau${array[*]}
subjek hasil ekspansi itu untuk pemecah kata lebih lanjut, sehingga Anda akan berakhir dengan kata-kata terpecah pada spasi (dan apa pun di$IFS
dalamnya) alih-alih satu kata per elemen array.Menggunakan C-style untuk loop juga baik dan menghindari mengkhawatirkan pemisahan kata jika Anda tidak jelas tentang itu:
sumber
Melarikan diri berhasil.
Keluaran:
Mengutip string juga menghasilkan output yang sama.
sumber
Jika Anda memiliki array seperti ini: #! / Bin / bash
Anda akan mendapatkan:
Saya tidak tahu mengapa tetapi loop memecah spasi dan menempatkannya sebagai item individual, bahkan Anda mengelilinginya dengan tanda kutip.
Untuk menyiasatinya, alih-alih memanggil elemen dalam array, Anda memanggil indeks, yang mengambil string penuh yang dibungkus dengan tanda kutip. Itu harus dibungkus dengan tanda kutip!
Maka Anda akan mendapatkan:
sumber
Bukan jawaban yang tepat untuk masalah kutipan / lolos dari pertanyaan awal, tetapi mungkin sesuatu yang sebenarnya akan lebih berguna untuk op:
Dimana tentu saja ungkapan tersebut harus diadopsi dengan persyaratan khusus (misalnya
*.jpg
untuk semua atau2001-09-11*.jpg
hanya untuk gambar-gambar pada hari tertentu).sumber
Solusi lain menggunakan loop "while" sebagai ganti loop "for":
sumber
Jika Anda tidak terjebak untuk menggunakan
bash
, penanganan spasi yang berbeda dalam nama file adalah salah satu manfaat dari kulit ikan . Pertimbangkan direktori yang berisi dua file: "a b.txt" dan "b c.txt". Berikut adalah perkiraan yang masuk akal dalam memproses daftar file yang dihasilkan dari perintah lainbash
, tetapi gagal karena spasi dalam nama file yang Anda alami:Dengan
fish
, sintaks hampir identik, tetapi hasilnya adalah apa yang Anda harapkan:Ini bekerja secara berbeda karena ikan membagi output perintah pada baris baru, bukan spasi.
Jika Anda memiliki kasus di mana Anda ingin membagi pada spasi alih-alih baris baru,
fish
memiliki sintaks yang sangat mudah dibaca untuk itu:sumber
Saya biasa mereset nilai IFS dan rollback setelah selesai.
Output yang mungkin dari loop:
sumber