Bagaimana cara menulis script bash yang melewati setiap direktori di dalam parent_directory dan mengeksekusi sebuah perintah di setiap direktori .
Struktur direktori adalah sebagai berikut:
parent_directory (nama bisa berupa apa saja - tidak mengikuti pola)
- 001 (nama direktori mengikuti pola ini)
- 0001.txt (nama file mengikuti pola ini)
- 0002.txt
- 0003.txt
- 002
- 0001.txt
- 0002.txt
- 0003.txt
- 0004.txt
- 003
- 0001.txt
jumlah direktori tidak diketahui.
cd "$d"
akan lebih baik karena transfer ke situasi di mana wildcard tidak cocok dengan file yang namanya berisi meta karakter spasi dan / atau shell.for f in foo bar; do cat "$f"/*.txt; done >output
secara fungsional setara dengancat foo/*.txt bar/*.txt >output
. Namun,ls
adalah satu perintah yang memang menghasilkan output yang sedikit berbeda tergantung pada bagaimana Anda menyampaikannya argumen; demikian pula,grep
atauwc
yang menghasilkan nama file relatif akan berbeda jika Anda menjalankannya dari subdirektori (tetapi sering kali, Anda ingin menghindari masuk ke subdirektori justru karena alasan itu).Jawaban ini diposting oleh Todd membantu saya.
The
\( ! -name . \)
Menghindari mengeksekusi perintah di direktori saat ini.sumber
find FOLDER* -maxdepth 0 -type d \( ! -name . \) -exec bash -c "cd '{}' && pwd" \;
-exec bash -c 'cd "$0" && pwd' {} \;
karena beberapa direktori berisi tanda kutip tunggal dan beberapa tanda kutip ganda.-mindepth 1
pwd
secara langsung?disd(){find . -maxdepth 1 -type d \( ! -name . \) -exec bash -c 'cd "{}" && "$@"' \;}
tidak bekerja.Jika Anda menggunakan GNU
find
, Anda dapat mencoba-execdir
parameter, misalnya:atau (sesuai komentar @gniourf_gniourf ):
Catatan: Anda bisa menggunakan
${0#./}
alih-alih$0
memperbaiki./
di depan.atau contoh yang lebih praktis:
Jika Anda ingin memasukkan direktori saat ini, itu bahkan lebih sederhana dengan menggunakan
-exec
:atau menggunakan
xargs
:Atau contoh serupa yang disarankan oleh @gniourf_gniourf :
Contoh di atas mendukung direktori dengan spasi di namanya.
Atau dengan menetapkan ke dalam bash array:
Ubah
.
nama folder spesifik Anda. Jika Anda tidak perlu menjalankan secara rekursif, Anda dapat menggunakan:dirs=(*)
sebagai gantinya. Contoh di atas tidak mendukung direktori dengan spasi di namanya.Jadi seperti yang disarankan @gniourf_gniourf , satu-satunya cara yang tepat untuk meletakkan output find dalam array tanpa menggunakan loop eksplisit akan tersedia di Bash 4.4 dengan:
Atau bukan cara yang disarankan (yang melibatkan penguraian
ls
):Contoh di atas akan mengabaikan dir saat ini (seperti yang diminta oleh OP), tetapi itu akan merusak nama dengan spasi.
Lihat juga:
sumber
find
dalam array tanpa menggunakan loop eksplisit akan tersedia di Bash 4.4 denganmapfile -t -d '' dirs < <(find . -type d -print0)
. Sampai saat itu, satu-satunya pilihan Anda adalah menggunakan loop (atau menunda operasi untukfind
).dirs
array; Anda bisa loop padafind
keluaran 's (aman) seperti:find . -type d -print0 | while IFS= read -r -d '' file; do ...; done
.IFS
,read
, memberikan kesan kompleksitas tambahan. Saya harus memikirkannya, mungkin ada beberapa cara yang lebih mudah untuk melakukannya.IFS
danread
(seperti yang Anda katakan) menjadi sifat kedua ketika Anda terbiasa dengan mereka ... mereka adalah bagian dari cara kanonik dan idiomatik cara menulis skrip.find . -type d -execdir echo $(pwd)/{} ';'
Anda tidak melakukan apa yang Anda inginkan ($(pwd)
diperluas sebelumfind
bahkan dieksekusi) ...Anda dapat mencapai ini dengan memipis dan kemudian menggunakan
xargs
. Tangkapannya adalah Anda harus menggunakan-I
flag yang akan menggantikan substring di perintah bash Anda dengan substring yang dilewati oleh masing-masingxargs
.Anda mungkin ingin mengganti
pwd
dengan perintah apa pun yang ingin Anda jalankan di setiap direktori.sumber
Jika folder tingkat atas diketahui, Anda bisa menulis sesuatu seperti ini:
Pada $ (MAINKAN BANYAK YANG ANDA INGINKAN); Anda dapat memasukkan kode sebanyak yang Anda inginkan.
Perhatikan bahwa saya tidak "cd" pada direktori apa pun.
Bersulang,
sumber
ls
" di sini - Anda bisa melakukannyafor dir in $YOUR_TOP_LEVEL_FOLDER/*
saja.ls $dir
ungkapansumber
Sementara satu liner bagus untuk penggunaan cepat dan kotor, saya lebih suka versi verbose di bawah ini untuk menulis skrip. Ini adalah template yang saya gunakan yang menangani banyak kasus tepi dan memungkinkan Anda untuk menulis kode yang lebih kompleks untuk dieksekusi pada folder. Anda dapat menulis kode bash Anda di fungsi dir_command. Di bawah ini, dir_coomand mengimplementasikan pemberian tag pada setiap repositori di git sebagai contoh. Sisa dari skrip memanggil dir_command untuk setiap folder dalam direktori. Contoh iterasi melalui hanya set folder yang diberikan juga termasuk.
sumber
Saya tidak mengerti dengan format file, karena Anda hanya ingin beralih melalui folder ... Apakah Anda mencari sesuatu seperti ini?
sumber
kamu bisa memakai
untuk mencari semua file / direktori dalam direktori saat ini secara rekursif
Daripada Anda bisa mem-pipe output, perintah xargs seperti itu
sumber
sumber
cd
subshell.cd
sehingga kode ini tidak benar-benar melakukan sesuatu yang bermanfaat.