Saya ingin melakukan sesuatu berulang kali pada daftar file. File dalam pertanyaan memiliki spasi dalam namanya:
david@david: ls -l
total 32
-rw-rw-r-- 1 david david 13 Mai 8 11:55 haha
-rw-rw-r-- 1 david david 0 Mai 8 11:55 haha~
-rw-rw-r-- 1 david david 13 Mai 8 11:55 haha (3rd copy)
-rw-rw-r-- 1 david david 13 Mai 8 11:55 haha (4th copy)
-rw-rw-r-- 1 david david 13 Mai 8 11:55 haha (5th copy)
-rw-rw-r-- 1 david david 13 Mai 8 11:55 haha (6th copy)
-rw-rw-r-- 1 david david 13 Mai 8 11:55 haha (7th copy)
-rw-rw-r-- 1 david david 13 Mai 8 11:55 haha (another copy)
-rw-rw-r-- 1 david david 13 Mai 8 11:55 haha (copy)
Sekarang saya ingin memberi stat pada masing-masing file ini:
david@david: echo '
for file in $(ls)
do
stat $file
done' | bash
(Saya menggunakan gema dan pipa untuk menulis perintah multi-line.)
Ketika saya melakukan itu, itu berfungsi dengan benar pada file-file yang tidak memiliki spasi di namanya. Tapi yang lain ...
stat: cannot stat ‘(another’: No such file or directory
stat: cannot stat ‘copy)’: No such file or directory
Mengubah $(ls)
ke "$(ls)"
atau $file
ke "$file"
tidak bekerja. Apa yang dapat saya?
Edit:
echo '
for files in *
do
stat "$files"
done' | bash
lakukan triknya! Karena saya baru mengenal bash, saya ingin menjaga hal-hal sesederhana mungkin - jadi tidak ada yang mencoba keluar dari ruang, atau menggunakan xargs
atau solusi read -r
, meskipun mereka memecahkan masalah.
Seperti beberapa orang bertanya: Ya, menggunakan ini bukan stat *
aneh. Tapi saya hanya ingin menemukan cara umum untuk menerapkan perintah yang sama pada banyak nama file di bash, menggunakan for for. Jadi stat
bisa berdiri untuk gzip
, gpg
atau rm
.
sumber
stat *
? (;-)Jawaban:
Kutipan berganda dari yang
echo '
memperumit masalah.Anda bisa menggunakan:
Tetapi juga
... dan jika Anda ingin mengumpulkan file dan kemudian menerapkan perintah (mengapa?) Anda dapat pergi dengan (tetapi hati-hati dengan file yang berisi baris baru ... (1))
... dan jika Anda ingin file tersembunyi juga, gunakan saja
* .*
sebagai pola, tetapi kemudian ingat itu.
dan..
akan di set .Sebagai tambahan, Anda tidak harus mengurai
ls
output .(1) tetapi jika Anda memiliki nama file dengan baris baru, Anda agak layak mendapatkannya ... ;-)
sumber
for f in *; do command "$f"; done
. Tidak pernah parsels
, tentu tidak pernah melakukannya dalam satufor
lingkaran dan mengapa menggunakanecho
?do
,|
,&&
dll, Anda dapat melanjutkan pada baris baru. Entah itu atau menggunakan heredocs. Tidak ada alasan untuk menggunakanecho
dan itu juga dapat menyebabkan masalah.Di samping catatan: Anda dapat membagi perintah panjang / rumit di beberapa baris dengan menambahkan spasi diikuti dengan garis miring terbalik dan mengenai Entersetiap kali Anda ingin mulai menulis ke baris baru, alih-alih memalsukan banyak proses dengan menggunakan
echo [...] | bash
; Anda juga harus menyertakan$file
tanda kutip ganda, untuk mencegah agar tidakstat
pecah jika nama file mengandung spasi:Masalahnya adalah bahwa
$(ls)
memperluas ke daftar nama file yang mengandung spasi, dan hal yang sama akan terjadi juga dengan"$(ls)"
.Bahkan memecahkan masalah ini, metode ini masih akan memecah pada nama file yang mengandung garis miring terbalik dan pada nama file yang mengandung baris baru (seperti yang ditunjukkan oleh terdon).
Solusi untuk kedua masalah tersebut adalah menyalurkan output
find
kewhile
loop yang dijalankanread -r
sehingga, pada setiap iterasi,read -r
akan menyimpan satu barisfind
output ke$file
:sumber
ls
. Pernah.ls
. Ada cara yang lebih baik dan lebih kuat. Anda mungkin juga ingin membaca ini: Mengapa * tidak * parse `ls`? untuk lebih jelasnya.ls
, itufor
-for
iterates atas (IFS dipisahkan) kata-kata yang diberikan setelah katain
kunci`for
danls
.for f in *
akan baik-baik saja, misalnya.Gunakan yang lama
find
, bekerja dengan file tersembunyi, baris baru dan spasi.atau yang lain sebagai gantinya
stat
sumber
Sebagai seorang pria R, saya sudah menemukan solusi di R:
Saya tahu, ini gila. Saya berharap output dari
ls
akan lebih mudah diurai ... R dapat menangani spasi, karena dir () mengembalikan nilai karakter yang dikutip. Apa pun di antara tanda kutip maka nama file yang valid dengan spasi.sumber
for f in *
, tekan enter dan lanjutkan pada baris baru:,do
tekan enter lagistat "$f"
,, enter lagi,done
enter. Itu adalah perintah yang dibagi dengan baik pada 4 baris dan tidak akan merusak jenis nama file apa pun.Saya telah mengalami contoh lain dari masalah spasi putih untuk loop, jadi perintah (imo lebih kuat) berikut adalah apa yang biasanya saya gunakan. Ini juga cocok dengan pipa.
Anda bisa menggabungkan ini dengan
grep
atau menggunakanfind
:sumber
-E
opsigrep
, yang tanpanya ia tidak akan mengenali+
dalam ekspresi reguler. Meski begitu, ini adalah ayunan dan rindu pada pertanyaan ini, karena Andagrep
menghapus nama file yang mengandung spasi . Itu juga menghapus nama file yang mengandung digit (angka) dan tanda baca (mis., Tanda kurung), seperti contoh dalam pertanyaan. Dan itu bahkan tidak menyebutkan nama file yang berisi baris baru atau mulai dengan-
(tanda hubung).Jawaban ini akan memecahkan masalah penguraian
ls
dan merawat backspaces dan baris baruCoba ini, itu akan menyelesaikan masalah Anda menggunakan Internal Field Separator IFS.
Tetapi Anda juga dapat dengan mudah menyelesaikannya tanpa perlu mengurai output menggunakan
sumber
IFS
sini: mengutip variabel harus cukup untuk mencegah pemisahan kata, tentunya?ls
.Sebagai gantinya, Anda dapat mengganti nama file Anda menggantikan ruang dengan beberapa karakter lain seperti garis bawah, sehingga Anda menyingkirkan masalah ini:
Untuk melakukannya, jalankan perintah dengan mudah:
sumber