¿Por qué este comando ffmpeg funciona en bash y no en zsh?

17

Hoy llegué a casa del trabajo (ejecuté bash en un cuadro de Ubuntu) e intenté ejecutar algún código en mi cuadro de arco local con mi amado zsh y los comandos fallaban.

El comando está debajo con la información personal y la ip cambiada obviamente

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

Funciona perfecto en bash, pero cuando lo ejecuto en zsh obtengo el error

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

¿Por qué me ha traicionado mi amado zsh?

John Allard
fuente
77
Intente poner el enlace rtsp entre comillas simples.
jimmij
1
eres mi héroe :) Sabía que zsh no me decepcionaría.
John Allard
1
Intente después mkdir -p 'rtsp://user:[email protected]:5554/my-media/media.amp-videocodec=h264'y luego bash y zsh le fallarán. Al menos zsh te muestra tu error aquí.
Stéphane Chazelas
@cuonglm, quise decir que cuando hay un archivo que coincide con el patrón, tanto zsh como bash "fallarán" en que el globo se expandirá. El comportamiento de zsh es más sensato porque cuando no hay coincidencia, te hace darte cuenta de tu error.
Stéphane Chazelas

Respuestas:

43

En cadena:

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

que tiene ?en esa cadena, por lo que el shell realizará la expansión del nombre de ruta en esa cadena, utilizando reglas de coincidencia de patrones .

En bash, si failglobno se configuraron las opciones, que es el valor predeterminado, el patrón fallido se dejará como está:

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

Mientras zshque no informará ningún error de coincidencia de patrón con la nomatchopción establecida, que es el valor predeterminado:

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

Puedes hacer zsh suprimir el error e imprimir el patrón:

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

Puedes hacer que te bashcomportes como zshconnomatch conjunto de opciones, activando failglob:

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

Más en general, puede deshabilitar la generación de nombres de shell:

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

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

o usando uno de shell citando métodos de para hacer que los convites de shell ?y otros patrones especiales coincidan con caracteres especiales literalmente.


zshtambién proporcione el noglobincorporado, que deshabilita la generación de nombre de archivo en cualquier palabra para el siguiente comando simple:

$ noglob echo *
*
Cuonglm
fuente
oh wow, es un poco vergonzoso haberse perdido, gracias por la buena respuesta.
John Allard
Pero ahora esto me hace preguntar: ¿cómo podría alguien solucionarlo? ¿Usando comillas? ¿Algo más? ¿Cat + subshells demasiado complicados? Sería bueno si agregara esto a su respuesta, para hacerlo un poco más general y aún así muy completo y correcto.
Ismael Miguel
Ahora que es una respuesta increíble! He votado en consecuencia. La respuesta fue realmente la última falta. Dijo lo que está mal, pero no la solución. Gracias.
Ismael Miguel
Otra alternativa: en zsh, puede deshabilitar el globbing solo para el comando actual al anteponer noglobel comando. Por ejemplo noglob echo *, simplemente saldrá *.
wjv