Saya cukup baru dalam skrip Bash. Saya memiliki "skrip test", yang saya gunakan sebagai dasar untuk skrip yang lebih maju / berguna:
#!/bin/bash
files=$1
for a in $files
do
echo "$a"
done
Ketika saya memanggil ini tanpa tanda kutip, itu hanya mengambil satu file di direktori:
testscript *.txt
Tetapi ketika saya menyebutnya dengan tanda kutip, ia bekerja dengan benar dan memilih semua file teks:
testscript '*.txt'
Apa yang terjadi disini?
bash
shell-script
gornvix
sumber
sumber
for a in "$@"; do
(ataufor a; do
) dalam skrip Anda, sehingga meninggalkan globbing ke kulit terluar, bukan untuk meninggalkan tanda kutip.Jawaban:
Saat Anda memanggil suatu program
maka shell Anda melakukan ekspansi dan menghitung semua nilai. Jadi mungkin, secara efektif memanggil program Anda sebagai
Sekarang program Anda hanya melihat
$1
dan hanya berfungsifile1.txt
.Dengan mengutip pada baris perintah Anda memberikan string literal
*.txt
ke skrip, dan itulah yang disimpan$1
.for
Lingkaran Anda lalu perluas.Biasanya Anda akan menggunakan
"$@"
dan tidak$1
dalam skrip seperti ini.Ini adalah "gotcha" untuk orang-orang yang berasal dari skrip CMD, di mana shell perintah tidak melakukan globbing (seperti diketahui) dan selalu melewati string literal.
sumber
"$@"
(sebagai lawan$@
atau$1
$2
$3
) akan menyebabkan setiap nama file dikutip"file1.txt"
"file2.txt"
dll. Untukfile1.txt
ini tidak ada artinya, tetapi jika Anda punyamy file.txt
, kutipan sangat penting untuk mencegah shell parsing untuk mengubahnya menjadi dua nama file, satu bernamamy
dan satu bernamafile.txt
. Selalu kutip input pengguna dan ekspansi glob agar Anda tidak bahagia suatu hari nanti.Tanpa tanda kutip shell mengembang
*.txt
sebelum menjalankan script, jadi$1
hanya file pertama yang diperluas. Semuatxt
file adalah argumen untuk skrip Anda pada saat itu (dengan asumsi tidak terlalu banyak).Dengan kutipan bahwa string dilewatkan tanpa diperluas ke skrip, yang kemudian memungkinkan
for
melakukan ekspansi, seperti yang Anda harapkan.sumber