Dlaczego to polecenie ffmpeg działa w bash, a nie w zsh?

17

Dzisiaj wróciłem do domu z pracy (uruchom bash na pudełku Ubuntu) i próbowałem uruchomić kod na moim lokalnym Arch Arch z moim ukochanym Zsh, a polecenia zawiodły?

Polecenie znajduje się poniżej, a dane osobowe i adres IP zmieniły się oczywiście

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

Działa idealnie w bash, ale kiedy uruchamiam go w Zsh, pojawia się błąd

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

Dlaczego mój ukochany Zsh mnie zdradził?

John Allard
źródło
7
Spróbuj umieścić link rtsp w pojedynczych cudzysłowach.
jimmij
1
jesteś moim bohaterem :) Wiedziałam, że Zsh mnie nie zawiedzie.
John Allard
1
Spróbuj później, mkdir -p 'rtsp://user:[email protected]:5554/my-media/media.amp-videocodec=h264'a wtedy zarówno bash, jak i zsh cię nie zawiodą. Przynajmniej zsh pokazuje ci twój błąd tutaj.
Stéphane Chazelas
@cuonglm, miałem na myśli, że gdy plik pasuje do wzorca, zarówno zsh, jak i bash „zakończą się niepowodzeniem”, ponieważ glob zostanie rozszerzony. zachowanie zsh jest zdrowsze, ponieważ kiedy nie ma żadnego dopasowania, uświadamiasz sobie swój błąd.
Stéphane Chazelas

Odpowiedzi:

43

W ciąg:

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

masz ?w tym ciągu, więc powłoka wykona rozwinięcie nazwy ścieżki w tym ciągu, używając reguł dopasowania wzorca .

W bash, jeśli failglobopcje nie zostały ustawione, co jest ustawieniem domyślnym, nieudany wzór pozostanie niezmieniony:

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

Chociaż zshnie zgłosi błędu dopasowania wzorca przy nomatchustawionej opcji, która jest domyślna:

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

Możesz zshusunąć błąd i wydrukować wzór:

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

Możesz ustawić bashzachowanie tak, jak w zshprzypadku nomatchzestawu opcji, włączając failglob:

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

Mówiąc bardziej ogólnie, możesz wyłączyć generowanie nazw plików powłoki:

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

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

lub używając jednej z metod cytowania powłoki , aby ?dosłownie traktować powłokę i inne znaki specjalne pasujące do wzorca.


zshtakże noglobwbudowane, które wyłączają generowanie nazw plików w dowolnych słowach dla następującego prostego polecenia:

$ noglob echo *
*
Cuonglm
źródło
och wow, to trochę krępujące, że przeoczyłem, dziękuję za miłą odpowiedź.
John Allard,
Ale teraz rodzi się pytanie: jak ktoś to naprawi? Korzystając z cytatów? Coś innego? Zbyt skomplikowane skorupy cat +? Byłoby miło, gdybyś dodał to do swojej odpowiedzi, aby uczynić ją bardziej ogólną, a jednocześnie bardzo kompletną i poprawną.
Ismael Miguel
Teraz TO jest niesamowita odpowiedź! Głosowałem odpowiednio. Naprawdę brakowało odpowiedzi. Powiedział, co jest nie tak, ale nie naprawił. Dziękuję Ci.
Ismael Miguel
Inna alternatywa: w zsh można wyłączyć globowanie tylko dla bieżącego polecenia, poprzedzając noglobpolecenie. Np. Po noglob echo *prostu wyjdzie *.
wjv 12.04.16