Saya menggunakan Bash 4.3.48(1) di Ubuntu 16.04 (xenial) dengan tumpukan LEMP.
Saya mencoba membuat php.ini
menimpa file dengan cara agnostik versi dengan printf
.
1) Operasi agnostik versi gagal:
printf "[PHP]n post_max_size = 200Mn upload_max_filesize = 200Mn cgi.fix_pathinfo = 0" > /etc/php/*/fpm/zz_overrides.ini
Kesalahan berikut diberikan:
bash:/etc/php/*/zz_overrides.ini:Tidak ada file atau direktori seperti itu
2) Operasi versi gnostik berhasil:
printf "[PHP]n post_max_size = 200Mn upload_max_filesize = 200Mn cgi.fix_pathinfo = 0" > /etc/php/7.0/fpm/zz_overrides.ini
Seperti yang Anda lihat, keduanya pada dasarnya identik selain *
vs 7.0
.
- Saya tidak menemukan petunjuk tentang masalah (regex?) ini di
man printf
. - Saya menelusuri di Google dan tidak menemukan apa pun tentang "mengizinkan regex di printf".
Mengapa operasi versi agnostik gagal dan apakah ada bypass?
Edit:Jika memungkinkan, sangat penting bagi saya untuk menggunakan operasi satu baris.
Jawaban yang Diterima:
Perilaku kecocokan pola dalam pengalihan tampaknya berbeda di antara shell. Dari yang ada di sistem saya, tanda hubung dan ksh93 tidak memperluas polanya, jadi Anda mendapatkan nama file dengan *
literal . Bash memperluasnya, tetapi hanya jika polanya cocok dengan satu file. Itu mengeluh jika ada lebih banyak nama file yang cocok. Zsh berfungsi seolah-olah Anda memberikan beberapa pengalihan, itu mengarahkan output ke semua file yang cocok.
(1) kecuali saat non-interaktif dan dalam mode POSIX
Jika Anda ingin output masuk ke semua file yang cocok, Anda dapat menggunakan tee
:
echo ... | tee /path/*/file > /dev/null
Jika Anda ingin pergi ke satu file saja, masalahnya adalah memutuskan mana yang akan digunakan. Jika Anda ingin memeriksa bahwa hanya ada satu file yang cocok dengan pola, perluas seluruh daftar dan hitung.
Dalam bash/ksh:
names=(/path/*/file)
if [ "${#names[@]}" -gt 1 ] ; then
echo "there's more than one"
else
echo "there's only one: ${names[0]}"
fi
Di shell standar, set
parameter posisi dan gunakan $#
untuk hitungan.
Tentu saja, jika polanya tidak cocok dengan file apa pun, itu dibiarkan apa adanya, dan karena glob berada di tengah, hasilnya menunjuk ke direktori yang tidak ada. Sama halnya dengan mencoba membuat /path/to/file
, sebelum /path/to
ada, hanya di sini kita memiliki /path/*
sebagai gantinya, secara harfiah, dengan tanda bintang.
Untuk mengatasinya, Anda harus memperluas nama direktori tanpa nama file, dan kemudian menambahkan nama file ke semua direktori. Ini agak jelek…
dirs=(/path/*)
files=( "${dirs[@]/%//file}" )
dan kemudian kita dapat menggunakan array itu:
echo ... | tee "${files[@]}" > /dev/null
Atau kita bisa mengambil jalan keluar yang mudah dan mengulang pola nama file. Ini agak tidak memuaskan dalam kasus yang lebih umum, karena memerlukan menjalankan perintah utama sekali untuk setiap file output, atau menggunakan file sementara untuk menyimpan output.
for dir in /path/* ; do
echo ... > "$dir/file"
done