17

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?

  • 7
    Try to put rtsp link into single quotes. – jimmij Mar 22 '16 at 6:10
  • 1
    you're my hero :) I knew zsh wouldn't let me down. – John Allard Mar 22 '16 at 6:16
  • 1
    Try after mkdir -p 'rtsp://user:pass@my.webserver.org:5554/my-media/media.amp-videocodec=h264' and then both bash and zsh will fail you. At least zsh shows you your mistake here. – Stéphane Chazelas Mar 22 '16 at 7:02
  • @cuonglm, I meant that when there's a file matching the pattern, both zsh and bash will "fail" in that the glob will be expanded. zsh's behaviour is saner in that when there's no match, it makes you realise your mistake. – Stéphane Chazelas Mar 22 '16 at 9:08
43

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 *
*
  • oh wow that's kind of embarrassing to have missed, thanks for the nice reply. – John Allard Mar 22 '16 at 7:19
  • But now this makes me question: How would someone fix it? By using quotes? Something else? Overly-complicated cat+subshells? It would be nice if you added this to your answer, to make it a bit more general and still very complete and correct. – Ismael Miguel Mar 22 '16 at 9:44
  • Now THAT is an awesome answer! I've upvoted accordingly. The answer was really lacking the last bit. It told what's wrong but not the fix. Thank you. – Ismael Miguel Mar 22 '16 at 10:02
  • Another alternative: In zsh, you can disable globbing only for the current command by prepending noglob to the command. E.g. noglob echo * will simply output *. – wjv Apr 12 '16 at 8:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.