Jadi lakukan sesuatu seperti ini di bash
dan sebagian besar shell lainnya tidak akan berfungsi untuk membuat banyak subdirektori atau file di dalam subdirektori…
mkdir */test
touch */hello.txt
Tentu saja ada banyak cara untuk benar-benar melakukan ini, yang saya sukai adalah menggunakan find
bila memungkinkan daripada menggunakan for
loop, terutama untuk keterbacaan.
Tapi pertanyaan saya adalah, mengapa hal di atas tidak berhasil?
Dari apa yang saya pahami itu karena file/path tujuan lengkap tidak ada tetapi pasti itu hal yang baik jika saya mencoba mkdir
atau touch
. Saya selalu pindah dan tidak pernah benar-benar mempertanyakannya.
Tapi apakah ada yang punya penjelasan yang layak untuk ini yang akan membantu saya memahaminya untuk selamanya?
Jawaban yang Diterima:
Poin yang mungkin Anda lewatkan – yang dialami banyak orang,
terutama jika mereka memiliki pengalaman dengan sistem operasi lain sebelum mereka menggunakan *nix
– adalah bahwa, di banyak OS lain, wildcard di baris perintah biasanya diteruskan ke perintah untuk memproses seperti yang terlihat cocok. Misalnya, di Prompt Perintah Windows,
rename *.jpeg *.jpg
Sedangkan, di *nix, untuk menyederhanakan tugas
programmer dari masing-masing perintah (mis., mv
), karakter pengganti
(bila tidak dikutip atau diloloskan) ditangani oleh shell,
dengan cara yang tidak bergantung pada antarmuka dan fungsionalitas
dari perintah yang menjadi argumen karakter pengganti.
Sebagian besar program yang menggunakan nama file sebagai argumen baris perintah mengharapkan file tersebut ada
(ya, mkdir
dan touch
pengecualian untuk aturan itu,
seperti mkfifo
, mknod
, dan, sebagian, cp
, ln
, mv
, dan rename
;
dan mungkin ada yang lain),
jadi tidak masuk akal jika shell memperluas wildcard
ke nama untuk file yang tidak ada.
Dan untuk cangkangnya (dan maksud saya setiap shell –
Bourne, bash, csh, fish, ksh, zsh, dll...) untuk menangani pengecualian secara berbeda
mungkin akan terlalu merepotkan.
Yang mengatakan, ada beberapa cara untuk mendapatkan hasil seperti yang Anda inginkan.
Jika Anda tahu apa yang akan diekspansi oleh wildcard,
dan itu tidak lama, Anda dapat membuatnya dengan ekspansi brace:
touch {red,orange,yellow,green,blue,indigo,violet}/rgb.txt
Solusi yang lebih umum:
sh -c 'for arg do mkdir -- "$arg"/test; done' -- *
Gilles membantu saya menemukan cara lain
untuk melakukannya di bash.
benbradley=(*)
mkdir "${benbradley[@]/%//test}"
Jelas benbradley
hanya pengidentifikasi di sini; Anda dapat menggunakan nama apa saja
(mis., huruf apa saja).
Perlu beberapa kali percobaan untuk memperbaikinya, jadi izinkan saya menguraikannya:
identifier=value
membuat variabel (skalar) bernamaidentifier
(jika belum ada) dan memberikan nilaivalue
untuk itu.
Misalnya,G=Man
.
Anda dapat mereferensikan variabel skalar dengan$identifier
;
misalnya,$G
, atau, lebih amannya, sebagai${identifier}
.
Misalnya,$Gage
dan$Gilla
mungkin tidak terdefinisi,
tetapi${G}age
adalahManage
dan${G}illa
adalahManilla
.identifier=(value1 value2 … )
membuat variabel array bernamaidentifier
(jika belum ada) dan memberikan nilai yang tercantum padanya.
Misalnya,
spectrum=(red orange yellow green blue indigo violet)
atau
all_text_files=(*.txt)
$name
akan mereferensikan elemen pertama (dan karenanya cukup tidak berguna).
Anda dapat mereferensikan elemen arbitrer sebagai ${name[subscript]}
;
misalnya, ${spectrum[0]}
adalah red
dan ${spectrum[4]}
adalah blue
.
Dan Anda dapat menggunakan ${name[@]}
dan ${name[*]}
untuk mereferensikan seluruh larik.
Jadi, ini dia berkeping-keping:
" ${ benbradley[@] / % / /test } "
${parameter/pattern/string}
memperluas${parameter}
dan menggantikan kecocokan
terpanjang daripattern
denganstring
.- Jika
pattern
dimulai dengan#
,
harus cocok di awal nilai yang diperluasparameter
.
Jikapattern
dimulai dengan%
,
harus cocok di akhir nilaiparameter
.
Dengan kata lain,
%(the-rest_of_the_pattern)
bertindak seperti
(the-rest_of_the_regex)$
(ya, sepertinya agak mundur).
Jadi pattern
itu hanya %
seperti ekspresi reguler yang hanya $
–
cocok dengan akhir string input (ruang pencarian).
- Dan saya menggunakan
string
dari/test
.
Jadi ini menggantikan akhir parameter dengan/test
(yaitu, itu menambahkan/test
ke parameter). - Hal lain tentang
${parameter/pattern/string}
yang tidak intuitif adalah selalu diakhiri dengan}
.
Tidak perlu, dan tidak bisa , akhiri dengan/
ketiga .
Oleh karena itu, sebuah/
dalamstring
tidak dapat diartikan sebagai pembatas,
dan oleh karena itu kita dapat memilikistring
dari/test
tanpa perlu keluar dari/
. - Jika
parameter
adalah variabel array
yang disubskrip dengan@
atau*
,
operasi substitusi diterapkan ke setiap anggota larik secara bergantian. - Saat Anda mereferensikan array sebagai
${name[@]}
(bukan${name[*]}
) dan menempatkan hasilnya dalam tanda kutip ganda,
Anda mempertahankan integritas elemen larik
(yaitu, Anda mempertahankan spasi dan karakter khusus lainnya di dalamnya)
tanpa menggabungkan elemen terpisah ke dalam satu kata yang panjang.