18

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:[email protected]: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:[email protected]:5554/my-media/media.amp?videocodec=h264

Why has my beloved zsh betrayed me?

4
  • 8
    Try to put rtsp link into single quotes.
    – jimmij
    Commented Mar 22, 2016 at 6:10
  • 1
    you're my hero :) I knew zsh wouldn't let me down. Commented Mar 22, 2016 at 6:16
  • 2
    Try after mkdir -p 'rtsp://user:[email protected]:5554/my-media/media.amp-videocodec=h264' and then both bash and zsh will fail you. At least zsh shows you your mistake here. Commented Mar 22, 2016 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. Commented Mar 22, 2016 at 9:08

1 Answer 1

44

In string:

rtsp://user:[email protected]: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 *
*
4
  • oh wow that's kind of embarrassing to have missed, thanks for the nice reply. Commented Mar 22, 2016 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. Commented Mar 22, 2016 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. Commented Mar 22, 2016 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
    Commented Apr 12, 2016 at 8:23

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .