Saya ingin bertindak pada daftar subdirektori dalam direktori. Mempertimbangkan:
for x in x86-headers/*/C/populate.sh; do echo $x; done
Ini memberi
x86-headers/elf/C/populate.sh
x86-headers/gl/C/populate.sh
x86-headers/gmp/C/populate.sh
x86-headers/gnome2/C/populate.sh
x86-headers/gtk2/C/populate.sh
x86-headers/jni/C/populate.sh
x86-headers/libc/C/populate.sh
Tapi aku ingin nilai-nilai yang bersesuaian dengan bagian kedua dari jalan,
elf
, gl
, dll saya tahu bagaimana menanggalkan terkemuka x86-headers
.
for x in x86-headers/*/C/populate.sh; do i=${x##x86-headers/}; echo $i; done
pemberian yang mana
elf/C/populate.sh
gl/C/populate.sh
gmp/C/populate.sh
gnome2/C/populate.sh
gtk2/C/populate.sh
jni/C/populate.sh
libc/C/populate.sh
Saya juga tahu cara menghapus istilah nanti di jalan. Yaitu turun satu tingkat:
cd x86-headers
for x in */C/populate.sh; do i=${x%%/*}; echo $i; done
memberi
elf
gl
gmp
gnome2
gtk2
jni
libc
Tetapi, mencoba menggabungkan ini tidak berhasil. Yaitu
for x in x86-headers/*/C/populate.sh; do i=${${x##x86-headers}%%/*}; echo $i; done
memberi
bash: ${${x##x86-headers}%%/*}: bad substitution
Tidak diragukan lagi ini adalah sintaks yang salah, tetapi saya tidak tahu sintaks yang benar. Tentu saja mungkin ada cara yang lebih baik untuk melakukan ini. Jika saya menggunakan Python, saya akan menggunakan split /
untuk memecah setiap jalur menjadi daftar, dan kemudian memilih elemen kedua, tapi saya tidak tahu bagaimana melakukannya di bash.
EDIT: Terima kasih atas jawabannya. Saya seharusnya juga bertanya, apakah mungkin melakukan ini dengan mudah, dan jika demikian, bagaimana?
i=${x#*/}; i=${i%%/*}
adalah opsional, bukan?ash
/dash
akan menjalankan tugas dari kanan ke kiri (yang adalah bagaimana shell Bourne berperilaku) dan menyebabkan masalah dalam kasus ini.Ekspansi parameter tidak memungkinkan Anda untuk membuat ekspresi sarang, jadi Anda terpaksa melakukannya dalam dua langkah, dengan tugas:
Anda memang memiliki opsi untuk menggunakan array di sini, tapi saya pikir itu akan lebih rumit daripada PE di atas:
Lalu ada opsi ketiga menggunakan perintah eksternal. Dengan daftar file yang pendek ini biasanya merupakan opsi yang paling tidak efisien, tetapi ini akan menskalakan yang terbaik seiring dengan meningkatnya jumlah file:
sumber
zsh
memungkinkan bersarang.bash
.sumber
Berhati-hatilah menggunakan konstruk seperti di bawah ini:
Karena Anda akan dapat akhirnya melakukan
echo *
. Dalam hal ini, itu hanya lucu, tapi bisa jauh terburuk jika Anda root, AndaCWD
yaitu/
dan Anda ingin menghapus beberapa sub direktori dari/tmp
bukannya bergema mereka!Untuk memperbaikinya dalam bash, Anda dapat melakukan:
Perhatikan
shopt -u nullglob
pada akhir untuk mengembalikan perilaku bash default setelah loop.Solusi yang lebih portabel adalah:
( Substitusi
##
dan%%
Parameter valid dalam ksh88 ).Ikuti tautan ini untuk diskusi yang lebih lengkap tentang nullglob .
Perhatikan bahwa 3 solusi di atas gagal jika Anda memiliki direktori perantara dengan spasi di namanya. Untuk mengatasinya, gunakan tanda kutip ganda dalam substitusi variabel:
sumber
Untuk melakukan pencocokan pola pada nama path dengan mudah, Anda dapat mengatur
IFS
variabel shell/
dan kemudian menggunakan ekspansi parameter shell.Melakukan semua ini dalam sebuah subkulit membantu menjaga lingkungan shell induk tidak berubah!
sumber