Pourquoi cette commande ffmpeg fonctionne-t-elle en bash et non en zsh?

17

Aujourd'hui, je suis rentré du travail (exécuter bash sur une boîte Ubuntu) et j'ai essayé d'exécuter du code sur ma boîte d'archive locale avec mon bien-aimé zsh et les commandes échouaient?

La commande est ci-dessous avec les informations personnelles et l'ip changé évidemment

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

Il fonctionne parfaitement en bash, mais quand je l'exécute en zsh, j'obtiens l'erreur

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

Pourquoi mon bien-aimé zsh m'a trahi?

John Allard
la source
7
Essayez de mettre le lien rtsp entre guillemets simples.
jimmij
1
tu es mon héros :) Je savais que zsh ne me laisserait pas tomber.
John Allard
1
Essayez après mkdir -p 'rtsp://user:[email protected]:5554/my-media/media.amp-videocodec=h264'et bash et zsh vous échoueront. Au moins zsh vous montre votre erreur ici.
Stéphane Chazelas
@cuonglm, je voulais dire que quand il y a un fichier correspondant au modèle, zsh et bash "échoueront" dans la mesure où le glob sera développé. Le comportement de zsh est plus sain en ce sens que lorsqu'il n'y a pas de correspondance, cela vous fait réaliser votre erreur.
Stéphane Chazelas

Réponses:

43

En chaîne:

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

vous avez ?dans cette chaîne, donc le shell effectuera l' expansion du chemin d'accès sur cette chaîne, en utilisant des règles de correspondance de modèle .

Dans bash, si les failgloboptions n'ont pas été définies, ce qui est par défaut, le modèle échoué sera laissé tel quel:

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

While zshne signalera aucune erreur de correspondance de modèle avec le nomatchjeu d'options, qui est par défaut:

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

Vous pouvez faire zshsupprimer l'erreur et imprimer le motif:

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

Vous pouvez vous bashcomporter comme zshavec le nomatchjeu d'options en activant failglob:

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

Plus généralement, vous pouvez désactiver la génération de nom de fichier shell:

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

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

ou en utilisant l'une des méthodes de citation du shell pour que les gâteries du shell ?et les autres motifs correspondant aux caractères spéciaux soient littéralement.


zshfournissez également la fonction noglobintégrée, qui désactive la génération de nom de fichier dans n'importe quel mot pour la commande simple suivante:

$ noglob echo *
*
cuonglm
la source
oh wow c'est un peu gênant d'avoir manqué, merci pour la gentille réponse.
John Allard
Mais maintenant, cela me fait me demander: comment quelqu'un pourrait-il y remédier? En utilisant des guillemets? Autre chose? Chat + sous-coquilles trop compliqué? Ce serait bien si vous ajoutiez ceci à votre réponse, pour la rendre un peu plus générale et toujours très complète et correcte.
Ismael Miguel
Maintenant, c'est une réponse impressionnante! J'ai voté en conséquence. La réponse manquait vraiment le dernier morceau. Il a dit ce qui ne va pas mais pas la solution. Je vous remercie.
Ismael Miguel
Autre alternative: dans zsh, vous pouvez désactiver la globalisation uniquement pour la commande en cours en ajoutant noglobla commande à la commande. Par exemple, noglob echo *affichera simplement *.
wjv