GNU/Linux >> Belajar Linux >  >> Linux

Redirection Ke Nama File Globbed Gagal?

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 

Linux
  1. Pengalihan Io Dan Perintah Kepala?

  2. Bagaimana Cara Mengubah Nama File yang Mengandung Karakter?

  3. Grep Gagal Menemukan Teks Di File Ini?

  1. Pipes dan Redirection di Linux - Dijelaskan!

  2. Memahami file /etc/hosts di Linux

  3. Bagaimana saya tahu nama file skrip dalam skrip Bash?

  1. Hapus symlink ke direktori

  2. Penanganan nama file lintas platform di .NET Core

  3. Bagaimana cara menghapus file dengan nama aneh?