Tại sao lệnh ffmpeg này hoạt động trong bash mà không phải zsh?


17

Hôm nay tôi đi làm về (chạy bash trên hộp Ubuntu) và thử chạy một số mã trên hộp vòm cục bộ của tôi với zsh yêu quý của tôi và các lệnh có bị lỗi không?

Lệnh bên dưới với thông tin cá nhân và ip thay đổi rõ ràng

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

Nó chạy hoàn hảo trong bash, nhưng khi tôi chạy nó trong zsh tôi gặp lỗi

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

Tại sao zsh yêu quý của tôi đã phản bội tôi?


7
Cố gắng đặt liên kết rtsp vào dấu ngoặc đơn.
jimmij 22/03/2016

1
bạn là người hùng của tôi :) Tôi biết zsh sẽ không làm tôi thất vọng.
John Allard

1
Hãy thử sau mkdir -p 'rtsp://user:pass@my.webserver.org:5554/my-media/media.amp-videocodec=h264'và sau đó cả bash và zsh sẽ làm bạn thất bại. Ít nhất zsh cho bạn thấy lỗi của bạn ở đây.
Stéphane Chazelas

@cuonglm, ý tôi là khi có một tệp khớp với mẫu, cả zsh và bash sẽ "thất bại" trong đó toàn cầu sẽ được mở rộng. Hành vi của zsh sẽ an toàn hơn khi không có trận đấu, điều đó khiến bạn nhận ra sai lầm của mình.
Stéphane Chazelas

Câu trả lời:


43

Trong chuỗi:

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

bạn có ?trong chuỗi đó, vì vậy shell sẽ thực hiện mở rộng tên đường dẫn trên chuỗi đó, sử dụng các quy tắc khớp mẫu .

Trong bash, nếu failglobcác tùy chọn không được đặt, mặc định, thì mẫu không thành công sẽ được giữ nguyên:

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

Trong khi zshsẽ báo cáo không có lỗi khớp mẫu với nomatchtùy chọn được đặt, mặc định:

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

Bạn có thể khắc zshphục lỗi và in mẫu:

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

Bạn có thể thực hiện bashhành vi như zshvới nomatchbộ tùy chọn, bằng cách bật failglob:

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

Tổng quát hơn, bạn có thể vô hiệu hóa việc tạo tên tệp shell:

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

(hoặc set -o noglob, set +o noglob)

hoặc sử dụng một trong các phương pháp trích dẫn shell để xử lý shell ?và mẫu khác khớp với các ký tự đặc biệt theo nghĩa đen.


zshcũng cung cấp noglobnội dung, vô hiệu hóa việc tạo tên tệp bằng bất kỳ từ nào cho lệnh đơn giản sau:

$ noglob echo *
*

oh wow đó là loại xấu hổ đã bỏ lỡ, cảm ơn vì trả lời tốt đẹp.
John Allard

Nhưng bây giờ điều này khiến tôi đặt câu hỏi: Làm thế nào một người nào đó sẽ sửa nó? Bằng cách sử dụng dấu ngoặc kép? Thứ gì khác? Con mèo quá phức tạp + subshells? Sẽ thật tuyệt nếu bạn thêm câu này vào câu trả lời của mình, để làm cho nó chung chung hơn một chút và vẫn rất đầy đủ và chính xác.
Ismael Miguel

Bây giờ THAT là một câu trả lời tuyệt vời! Tôi đã nâng cao tương ứng. Câu trả lời thực sự thiếu chút cuối cùng. Nó nói những gì sai nhưng không phải là sửa chữa. Cảm ơn bạn.
Ismael Miguel

Một cách khác: Trong zsh, bạn chỉ có thể vô hiệu hóa toàn cầu cho lệnh hiện tại bằng cách thêm vào nogloblệnh. Eg noglob echo *sẽ chỉ đơn giản là đầu ra *.
wjv
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.