Почему эта команда ffmpeg работает в bash, а не в zsh?

17

Сегодня я вернулся домой с работы (запустил bash на коробке с Ubuntu) и попытался запустить какой-то код на моей локальной коробке с моим любимым zsh, и команды не выполнялись?

Команда внизу с личной информацией и ip явно изменилась

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

Он отлично работает в bash, но когда я запускаю его в zsh, я получаю сообщение об ошибке

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

Почему мой любимый зш предал меня?

Джон Аллард
источник
7
Попробуйте поместить ссылку RTSP в одинарные кавычки.
Джимми
1
ты мой герой :) Я знал, что Zsh не подведет меня.
Джон Аллард
1
Попробуй потом mkdir -p 'rtsp://user:pass@my.webserver.org:5554/my-media/media.amp-videocodec=h264'и тогда bash и zsh тебя не подведут. По крайней мере, Zsh показывает вам вашу ошибку здесь.
Стефан Шазелас
@cuonglm, я имел в виду, что когда есть файл, соответствующий шаблону, и zsh, и bash "потерпят неудачу", так как глобус будет расширен. Поведение zsh более разумно в том смысле, что когда нет совпадения, оно заставляет вас осознать свою ошибку.
Стефан Шазелас

Ответы:

43

В строке:

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

у вас есть ?в этой строке, поэтому оболочка будет выполнять расширение пути к этой строке, используя правила сопоставления с образцом .

В bash, если failglobпараметры не установлены, что по умолчанию, затем не шаблон будет оставлен как есть:

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

Хотя zshбудет сообщать об отсутствии совпадения с шаблоном с nomatchустановленным параметром, который используется по умолчанию:

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

Вы можете сделать zshподавление ошибки и распечатать шаблон:

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

Вы можете заставить bashсебя вести себя как zshс nomatchустановленной опцией, включив failglob:

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

В более общем смысле, вы можете отключить генерацию имени оболочки:

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

(или set -o noglob, set +o noglob)

или используя один из методов цитирования оболочки, чтобы ?буквально обрабатывать оболочку и другие шаблоны, соответствующие специальным символам.


zshтакже предоставьте noglobвстроенную функцию, которая отключает генерацию имени файла в любых словах для следующей простой команды:

$ noglob echo *
*
cuonglm
источник
Ого, это немного неловко, что я пропустил, спасибо за хороший ответ.
Джон Аллард
Но теперь это заставляет меня задаться вопросом: как бы кто-то это исправить? Используя кавычки? Что-то другое? Чрезмерно сложная кошка + подоболочки? Было бы неплохо, если бы вы добавили это в свой ответ, чтобы сделать его более общим и все же очень полным и правильным.
Исмаэль Мигель
Теперь это отличный ответ! Я проголосовал соответственно. Ответу действительно не хватало последней части. Он сказал, что не так, но не исправить. Спасибо.
Исмаэль Мигель
Другая альтернатива: в zsh вы можете отключить подстановку только для текущей команды, добавив noglobперед ней команду. Например, noglob echo *будет просто вывод *.
wjv