Quels caractères doivent être échappés dans les fichiers sans guillemets?

12

J'ai un shell / terminal basé sur un navigateur qui exécute les commandes bash et j'échappe aux espaces, mais il s'avère que les parenthèses doivent également être échappées. Quels autres caractères doivent être échappés pour les noms de fichiers qui ne sont pas entre guillemets?

jcubic
la source
Il n'est pas du tout clair de ce que vous essayez de faire. Et qu'est-ce que l'auto-complétion a à voir avec quoi que ce soit?
Michael Vehrs
@MichaelVehrs J'ai une commande mv filename filename-fooen bash, quels caractères dois-je échapper, à part les espaces et les parenthèses?
jcubic
@MichaelVehrs a supprimé la mention de saisie semi-automatique.
jcubic
Fondamentalement, tous les métacaractères du shell, tels que les espaces, les globes du shell, les événements d'historique. Pour cette raison, vous devez citer le nom de fichier entier, plutôt que de l' échappement des caractères individuels: mv "$filename" "$newname".
Michael Vehrs
@MichaelVehrs Je sais que la citation résoudra le problème de l'échappement, mais je dois utiliser le nom de fichier sans guillemets. J'ai un émulateur de terminal et cela devrait fonctionner lorsque l'utilisateur n'utilise pas de guillemets.
jcubic

Réponses:

22

La solution simple consiste à mettre un guillemet simple ( ') au début et un autre guillemet simple à la fin, et à remplacer chaque 'caractère à l'intérieur du nom de fichier par la séquence de 4 caractères '\''. Tous les caractères perdent leur signification particulière à l'intérieur d'une chaîne entre guillemets simples, sauf 'elle-même qui marque la fin de la chaîne. La séquence '\''termine le littéral entre guillemets simples, immédiatement suivie par un guillemet simple entre guillemets et ouvre un nouveau littéral entre guillemets simples. Ainsi le nom du fichier

This file's name has some weird characters!
Will you manage to escape them?

peut être cité comme suit:

somecommand 'This file'\''s name has some weird characters!
Will you manage to escape them?'

Les guillemets doubles ont des règles d'échappement plus complexes et ne vous permettent pas d'inclure un point d'exclamation !si la substitution d'historique est activée, donc je ne les examinerai pas plus loin.

Une autre approche consiste à protéger les personnages avec des barres obliques inverses. Cela fonctionne pour tous les personnages sauf les sauts de ligne; pour une nouvelle ligne, la mettre entre guillemets simples (ou doubles) est la seule solution. Si vous souhaitez réduire le nombre de barres obliques inverses pour présenter le nom cité à l'utilisateur, vous pouvez le limiter aux endroits où la barre oblique inverse est nécessaire; cependant, plus vous supprimez de barres obliques inverses, plus vous risquez d'oublier celle qui est nécessaire. Les lettres, les chiffres et les caractères non ASCII sont toujours corrects¹. Citez les espaces et la ponctuation lorsque vous n'êtes pas sûr.

Avec un shell typique (ksh, bash ou zsh), vous devez citer les caractères suivants dans au moins certaines circonstances.

  • Espace (espace, tabulation, nouvelle ligne - rappelant que les nouvelles lignes ne peuvent pas être citées avec une barre oblique inverse).
  • ! - expansion de l'histoire.
  • " - syntaxe du shell.
  • #- le commentaire commence lorsqu'il est précédé d'un espace; zsh wildcards.
  • $ - syntaxe du shell.
  • & - syntaxe du shell.
  • ' - syntaxe du shell.
  • (- même au milieu d'un mot: ksh globs étendus (également disponible en bash et zsh); zsh wildcards.
  • )(voir ()
  • * - sh joker.
  • , - uniquement à l'intérieur de l'expansion de l'orthèse.
  • ; - syntaxe du shell.
  • < - syntaxe du shell.
  • = - en zsh, quand il est au début d'un nom de fichier (extension de nom de fichier avec recherche PATH).
  • > - syntaxe du shell.
  • ? - sh joker.
  • [ - sh joker.
  • \ - syntaxe du shell.
  • ] - vous pouvez vous en sortir sans le mentionner.
  • ^- expansion historique; zsh wildcard.
  • ` - syntaxe du shell.
  • { - expansion du corset.
  • | - syntaxe du shell.
  • } - doit être échappé dans zsh, les autres coques sont plus indulgentes lorsqu'il n'y a pas d'accolade ouvrante correspondante.
  • ~- l'expansion du répertoire personnel lorsqu'elle se trouve au début d'un nom de fichier; zsh wildcard; toujours en sécurité quand c'est le dernier personnage.

Quelques caractères supplémentaires peuvent parfois nécessiter une manipulation spéciale:

  • -n'est pas spécial pour le shell, mais lorsqu'il se trouve au début d'un argument de commande, il indique une option. Il ne peut pas être protégé par des guillemets car le traitement spécial est dans la commande, pas dans le shell. Pour protéger un nom de fichier commençant par -, vous pouvez le mettre ./avant - de cette façon, c'est toujours le même fichier, mais l'argument ne commence -plus.
  • .n'est pas spécial en soi, mais les fichiers dot sont exclus des *globes par défaut.
  • :n'est pas spécial pour le shell, mais certaines commandes l'analysent spécialement, par exemple pour indiquer un fichier distant ( hostname:filename). Consultez la documentation de la commande pour voir comment gérer les fichiers de fichiers contenant des deux-points.

¹ À moins que l'utilisateur n'ait configuré d'autres caractères d'extension d'historique. Certains obus le permettent. C'est une autre raison d'utiliser des guillemets simples plutôt que des barres obliques inverses.

Gilles 'SO- arrête d'être méchant'
la source
Les sauts de ligne, au moins LFseulement, peuvent être cités avec une barre oblique inverse dans certains shells.
iBug
@iBug Non. Dans tout shell de type sh, la barre oblique inverse + nouvelle ligne se développe en une chaîne vide, pas en une nouvelle ligne.
Gilles 'SO- arrête d'être méchant'
Ceci est une bonne réponse, merci. Existe-t-il un lien vers où ces informations sont «officiellement» disponibles?
slashmais
1
@slashmais Quelles informations? La syntaxe du langage shell est «officiellement» disponible dans divers manuels et spécifications, mais passer de là à trouver exactement quels caractères doivent citer où n'est pas complètement simple.
Gilles 'SO- arrête d'être méchant'
1
J'ai également trouvé ceci: tecmint.com/manage-linux-filenames-with-special-characters - il n'est pas aussi compact que votre liste, mais contient de nombreux exemples. (au fait: "Quelles informations?" n'est pas une réponse sympa quand le sujet ici concerne les personnages)
slashmais