Mengapa perintah ffmpeg ini bekerja di bash dan bukan zsh?

17

Hari ini saya pulang kerja (jalankan bash pada kotak Ubuntu) dan mencoba menjalankan beberapa kode pada kotak lengkung lokal saya dengan zsh kesayangan saya dan perintahnya gagal?

Perintah di bawah ini dengan info pribadi dan ip berubah dengan jelas

ffmpeg -i rtsp://user:pass@my.webserver.org:5554/my-media/media.amp?videocodec=h264  -threads 3 -vcodec copy -f segment -segment_time 2 outfiles/cam_out%04d.mp4

Ini berjalan sempurna di bash, tetapi ketika saya menjalankannya di zsh saya mendapatkan kesalahan

zsh: no matches found: rtsp://user:pass@my.webserver.org:5554/my-media/media.amp?videocodec=h264

Mengapa zsh kesayanganku mengkhianatiku?

John Allard
sumber
7
Cobalah untuk menempatkan tautan rtsp ke dalam tanda kutip tunggal.
jimmij
1
Anda adalah pahlawan saya :) Saya tahu zsh tidak akan mengecewakan saya.
John Allard
1
Coba setelah mkdir -p 'rtsp://user:[email protected]:5554/my-media/media.amp-videocodec=h264'dan kemudian bash dan zsh akan mengecewakan Anda. Setidaknya zsh menunjukkan kesalahan Anda di sini.
Stéphane Chazelas
@cuonglm, saya maksudkan bahwa ketika ada file yang cocok dengan pola, baik zsh dan bash akan "gagal" karena glob akan diperluas. Perilaku zsh lebih waras dalam hal ketika tidak ada kecocokan, itu membuat Anda menyadari kesalahan Anda.
Stéphane Chazelas

Jawaban:

43

Dalam string:

rtsp://user:pass@my.webserver.org:5554/my-media/media.amp?videocodec=h264

Anda miliki ?di string itu, jadi shell akan melakukan ekspansi pathname pada string itu, menggunakan aturan pencocokan pola .

Dalam bash, jika failglobopsi tidak disetel, yang merupakan default, maka pola yang gagal akan dibiarkan apa adanya:

$ echo does-not-exist?
does-not-exist?

Sementara zshakan melaporkan tidak ada kesalahan pencocokan pola dengan nomatchset opsi, yang merupakan default:

$ echo does-not-exist?
zsh: no matches found: does-not-exist?

Anda dapat zshmenekan kesalahan dan mencetak polanya:

$ setopt nonomatch
$ echo does-not-exist?
does-not-exist?

Anda dapat bashberperilaku seperti zshdengan nomatchset opsi, dengan menghidupkan failglob:

$ shopt -s failglob
$ echo does-not-exist?
bash: no match: does-not-exist?

Lebih umum, Anda dapat menonaktifkan pembuatan nama file shell:

$ set -f
$ : "The command"
$ set +f

(atau set -o noglob, set +o noglob)

atau menggunakan salah satu metode mengutip shell untuk membuat suguhan shell ?dan pola lainnya cocok dengan karakter khusus secara harfiah.


zshjuga menyediakan noglobbuiltin, yang menonaktifkan pembuatan nama file dalam kata apa pun untuk perintah sederhana berikut:

$ noglob echo *
*
cuonglm
sumber
oh wow itu agak memalukan untuk dilewatkan, terima kasih atas jawaban yang bagus.
John Allard
Tetapi sekarang ini membuat saya bertanya: Bagaimana seseorang memperbaikinya? Dengan menggunakan kutipan? Sesuatu yang lain Kucing + subkulit yang terlalu rumit? Akan lebih baik jika Anda menambahkan ini ke jawaban Anda, untuk membuatnya sedikit lebih umum dan masih sangat lengkap dan benar.
Ismael Miguel
Sekarang, itu jawaban yang luar biasa! Saya telah memilih sesuai dengan itu. Jawabannya benar-benar kurang dari yang terakhir. Ia memberi tahu apa yang salah tetapi tidak memperbaikinya. Terima kasih.
Ismael Miguel
Alternatif lain: Di zsh, Anda dapat menonaktifkan globbing hanya untuk perintah saat ini dengan menambahkan noglobke perintah. Misalnya noglob echo *hanya akan menampilkan *.
wjv