Bash – Why does this ffmpeg command work in bash and not zsh

bashquotingurlzsh

Today I got home from work (run bash on an Ubuntu box) and tried to run some code on my local arch box with my beloved zsh and the commands were failing?

The command is below with the personal info and ip changed obviously

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

It runs perfect in bash, but when I run it in zsh I get the error

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

Why has my beloved zsh betrayed me?

Best Answer

In string:

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

you have ? in that string, so the shell will perform pathname expansion on that string, using pattern matching rules.

In bash, if failglob options was not set, which is default, then failed pattern will be left as-is:

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

While zsh will report no pattern match error with nomatch option set, which is default:

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

You can make zsh suppress the error and print the pattern:

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

You can make bash behave like zsh with nomatch option set, by turning on failglob:

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

More general, you can disable shell filename generation:

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

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

or using one of shell quoting methods to make the shell treats ? and other pattern matching special characters literally.


zsh also provide the noglob builtin, which disable filename generation in any words for the following simple command:

$ noglob echo *
*