Apakah ada yang punya skrip shell template untuk melakukan sesuatu dengan ls
daftar nama direktori dan perulangan masing-masing dan melakukan sesuatu?
Saya berencana melakukan ls -1d */
untuk mendapatkan daftar nama direktori.
sumber
Apakah ada yang punya skrip shell template untuk melakukan sesuatu dengan ls
daftar nama direktori dan perulangan masing-masing dan melakukan sesuatu?
Saya berencana melakukan ls -1d */
untuk mendapatkan daftar nama direktori.
Diedit untuk tidak menggunakan ls di mana gumpalan akan melakukan, seperti yang disarankan @ shawn-j-goff dan lainnya.
Cukup gunakan satu for..do..done
lingkaran:
for f in *; do
echo "File -> $f"
done
Anda dapat mengganti *
dengan *.txt
atau glob lain yang mengembalikan daftar (file, direktori, atau apa pun dalam hal ini), perintah yang menghasilkan daftar, misalnya $(cat filelist.txt)
, atau benar-benar menggantinya dengan daftar.
Di dalam do
loop, Anda cukup merujuk ke variabel loop dengan awalan tanda dolar (jadi $f
dalam contoh di atas). Anda dapat echo
melakukannya atau melakukan hal lain yang Anda inginkan.
Misalnya, untuk mengganti nama semua .xml
file di direktori saat ini menjadi .txt
:
for x in *.xml; do
t=$(echo $x | sed 's/\.xml$/.txt/');
mv $x $t && echo "moved $x -> $t"
done
Atau bahkan lebih baik, jika Anda menggunakan Bash Anda dapat menggunakan ekspansi parameter Bash daripada memunculkan subkulit:
for x in *.xml; do
t=${x%.xml}.txt
mv $x $t && echo "moved $x -> $t"
done
for
loop yang sangat umum , dan perangkap khas mencoba mengurai outputls
. @ DanielA.White, Anda mungkin mempertimbangkan untuk tidak menerima jawaban ini jika itu tidak membantu (atau berpotensi menyesatkan), karena seperti yang Anda katakan, Anda bertindak berdasarkan direktori. Jawaban Shawn J. Goff harus memberikan solusi yang lebih kuat dan berfungsi untuk masalah Anda.ls
output , Anda tidak harus membaca output dalam satufor
lingkaran , Anda harus menggunakan$()
alih-alih `` dan Use More Quotes ™ . Saya yakin @CoverosGene bermaksud baik, tetapi ini hanya mengerikan.ls
adalahls -1 | while read line; do stuff; done
. Setidaknya itu tidak akan rusak untuk ruang putih.mv -v
Anda tidak perluecho "moved $x -> $t"
Menggunakan output
ls
untuk mendapatkan nama file adalah ide yang buruk . Ini dapat menyebabkan skrip yang tidak berfungsi dan bahkan berbahaya. Ini karena nama file dapat berisi karakter apa pun kecuali/
dannull
karakternya, danls
tidak menggunakan salah satu dari karakter tersebut sebagai pembatas, jadi jika nama file memiliki spasi atau baris baru, Anda akan mendapatkan hasil yang tidak terduga.Ada dua cara yang sangat baik untuk mengulang file. Di sini, saya hanya menggunakan
echo
untuk menunjukkan melakukan sesuatu dengan nama file; Anda bisa menggunakan apa saja.Yang pertama adalah menggunakan fitur globbing asli shell.
Shell mengembang
*/
menjadi argumen terpisah yangfor
dibaca loop; bahkan jika ada spasi, baris baru, atau karakter aneh lainnya dalam nama file,for
akan melihat setiap nama lengkap sebagai unit atom; itu tidak menguraikan daftar dengan cara apa pun.Jika Anda ingin pergi secara rekursif ke subdirektori, maka ini tidak akan melakukan kecuali shell Anda memiliki beberapa fitur globbing diperpanjang (seperti
bash
'sglobstar
. Jika shell Anda tidak memiliki fitur ini, atau jika Anda ingin memastikan bahwa script Anda akan bekerja pada berbagai sistem, maka opsi selanjutnya adalah menggunakanfind
.Di sini,
find
perintah akan memanggilecho
dan memberikan argumen nama file. Ini melakukan ini sekali untuk setiap file yang ditemukannya. Seperti contoh sebelumnya, tidak ada penguraian daftar nama file; sebaliknya, nama file dikirim sepenuhnya sebagai argumen.Sintaks
-exec
argumen terlihat sedikit lucu.find
mengambil argumen pertama setelah-exec
dan menganggap itu sebagai program untuk dijalankan, dan setiap argumen berikutnya, dibutuhkan sebagai argumen untuk lolos ke program itu. Ada dua argumen khusus yang-exec
perlu dilihat. Yang pertama adalah{}
; argumen ini diganti dengan nama file yangfind
dihasilkan oleh bagian sebelumnya . Yang kedua adalah;
, yang memberifind
tahu ini adalah akhir dari daftar argumen untuk diteruskan ke program;find
membutuhkan ini karena Anda dapat melanjutkan dengan lebih banyak argumen yang ditujukan untukfind
dan tidak ditujukan untuk program eksekutif. Alasan untuk itu\
adalah bahwa shell juga memperlakukan;
khususnya - ia mewakili akhir dari sebuah perintah, jadi kita perlu menghindarinya sehingga shell memberikannya sebagai argumen untukfind
tidak menggunakannya untuk dirinya sendiri; Cara lain untuk mendapatkan shell untuk tidak memperlakukannya secara khusus adalah memasukkannya ke dalam tanda kutip:';'
berfungsi sama baiknya\;
untuk tujuan ini.sumber
find
. Ada keajaiban yang bisa dilakukan, dan bahkan keterbatasan yang dirasakan-exec
dapat diselesaikan. The-print0
pilihan juga berharga untuk digunakan denganxargs
.Untuk file dengan spasi di Anda harus memastikan untuk mengutip variabel seperti:
atau, Anda dapat mengubah variabel lingkungan pemisah bidang input (IFS):
Akhirnya, tergantung pada apa yang Anda lakukan, Anda bahkan mungkin tidak memerlukan ls:
sumber
\n
tidak cukup. Tidak pernah merupakan ide yang bagus untuk merekomendasikan parsing output darils
.Jika Anda telah menginstal GNU Parallel http://www.gnu.org/software/parallel/ Anda dapat melakukan ini:
Untuk mengganti nama semua .txt menjadi .xml:
Tonton video intro untuk GNU Parallel untuk mempelajari lebih lanjut: http://www.youtube.com/watch?v=OpaiGYxkSuQ
sumber
Hanya untuk menambahkan jawaban CoverosGene, berikut adalah cara untuk mendaftar hanya nama direktori:
sumber
Mengapa tidak mengatur IFS ke baris baru, lalu menangkap output
ls
dalam array? Pengaturan IFS ke baris baru harus menyelesaikan masalah dengan karakter lucu dalam nama file; menggunakanls
bisa menyenangkan karena memiliki fasilitas sortir bawaan.(Dalam pengujian saya mengalami kesulitan pengaturan IFS untuk
\n
tetapi pengaturannya untuk backspace karya baris baru, seperti yang disarankan di tempat lain di sini):Misalnya (dengan asumsi
ls
pola pencarian yang diinginkan diteruskan$1
):Ini sangat berguna pada OS X, misalnya, untuk mengambil daftar file yang diurutkan berdasarkan tanggal pembuatan (terlama ke terbaru),
ls
perintahnya adalahls -t -U -r
.sumber
\n
tidak cukup. Satu-satunya solusi yang valid menggunakan loop for dengan ekspansi pathname, ataufind
.Ini adalah bagaimana saya melakukannya, tetapi mungkin ada cara yang lebih efisien.
sumber
ls | while read i; do echo filename: $i; done