¿Qué caracteres se deben escapar en archivos sin comillas?

12

Tengo un shell / terminal basado en navegador que ejecuta comandos bash y escapo espacios, pero resulta que los paréntesis también deben escaparse. ¿Qué otros caracteres se deben escapar para los nombres de archivo que no están entre comillas?

jcubic
fuente
No está nada claro lo que está tratando de hacer. ¿Y qué tiene que ver el autocompletado con algo?
Michael Vehrs
@MichaelVehrs Tengo comando mv filename filename-fooen bash, ¿de qué caracteres necesito escapar, además de espacios y paréntesis?
jcubic
@MichaelVehrs eliminó la mención de autocompletar.
jcubic
Básicamente, todos los metacaracteres de shell, como espacios en blanco, globos de shell, eventos de historia. Por esta razón, se debe citar todo el nombre del archivo, en lugar de escapar caracteres individuales: mv "$filename" "$newname".
Michael Vehrs
@MichaelVehrs Sé que las citas resolverán el problema de la fuga, pero necesito usar el nombre de archivo sin comillas. Tengo un emulador de terminal y debería funcionar cuando el usuario no usa comillas.
jcubic

Respuestas:

22

La solución simple es poner una comilla simple ( ') al principio y otra comilla simple al final, y reemplazar cada 'carácter dentro del nombre del archivo por la secuencia de 4 caracteres '\''. Todos los caracteres pierden su significado especial dentro de una cadena entre comillas simples, excepto en 'sí mismo, que marca el final de la cadena. La secuencia '\''finaliza el literal entre comillas simples, inmediatamente sigue por una comilla simple entre comillas y abre un nuevo literal entre comillas simples. Por lo tanto, el nombre del archivo

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

se puede citar de la siguiente manera:

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

Las comillas dobles tienen reglas de escape más complejas y no le permiten incluir un signo de exclamación !si la sustitución del historial está activada, por lo que no las consideraré más.

Un enfoque alternativo es proteger a los personajes con barras invertidas. Esto funciona para todos los personajes excepto las líneas nuevas; para una nueva línea, ponerla entre comillas simples (o comillas dobles) es la única solución. Si desea minimizar el número de barras invertidas para presentar el nombre citado al usuario, puede restringirlo a los lugares donde se necesita la barra invertida; sin embargo, cuantas más barras invertidas omita, más se arriesga a olvidar una que sea necesaria. Las letras, los dígitos y los caracteres no ASCII siempre están bien¹. Cite espacios en blanco y signos de puntuación cuando no esté seguro.

Con un shell típico (ksh, bash o zsh), debe citar los siguientes caracteres en al menos algunas circunstancias.

  • Espacio en blanco (espacio, tabulación, nueva línea, recordando que las nuevas líneas no se pueden citar con una barra invertida).
  • ! - expansión de la historia.
  • " - sintaxis de shell.
  • #- comience el comentario cuando esté precedido por espacios en blanco; Comodines zsh.
  • $ - sintaxis de shell.
  • & - sintaxis de shell.
  • ' - sintaxis de shell.
  • (- incluso en medio de una palabra: ksh globs extendido (también disponible en bash y zsh); Comodines zsh.
  • )(ver ()
  • * - sh comodín.
  • , - solo dentro de la expansión del aparato ortopédico.
  • ; - sintaxis de shell.
  • < - sintaxis de shell.
  • = - en zsh, cuando está al comienzo de un nombre de archivo (expansión de nombre de archivo con búsqueda de RUTA).
  • > - sintaxis de shell.
  • ? - sh comodín.
  • [ - sh comodín.
  • \ - sintaxis de shell.
  • ] - puede salirse con la suya sin citarlo.
  • ^- expansión de la historia; comodín zsh.
  • ` - sintaxis de shell.
  • { - expansión de la abrazadera.
  • | - sintaxis de shell.
  • } - necesita ser escapado en zsh, otros shells son más indulgentes cuando no hay una llave de apertura correspondiente.
  • ~- expansión del directorio de inicio cuando está al comienzo de un nombre de archivo; comodín zsh; siempre a salvo cuando es el último personaje.

Algunos caracteres más pueden requerir un manejo especial a veces:

  • -no es especial para el shell, pero cuando está al comienzo de un argumento de comando, indica una opción. No se puede proteger con comillas ya que el manejo especial está en el comando, no en el shell. Para proteger un nombre de archivo que comienza con -, puede colocarlo ./antes; de esta manera sigue siendo el mismo archivo, pero el argumento ya no comienza -.
  • .no es especial en sí mismo, pero los archivos de puntos están excluidos de los *globos de forma predeterminada.
  • :no es especial para el shell, pero algunos comandos lo analizan especialmente, por ejemplo, para indicar un archivo remoto ( hostname:filename). Consulte la documentación del comando para ver cómo hacer frente a los nombres de archivo que contienen dos puntos.

¹ A menos que el usuario haya configurado caracteres de expansión de historial alternativos. Algunos proyectiles lo permiten. Esta es otra razón para usar comillas simples en lugar de barras invertidas.

Gilles 'SO- deja de ser malvado'
fuente
Las nuevas líneas, al menos LFsolo, se pueden citar con una barra diagonal inversa en algunos shells.
iBug
@iBug No. En cualquier shell similar a sh, la barra invertida + nueva línea se expande a una cadena vacía, no a una nueva línea.
Gilles 'SO- deja de ser malvado'
Esta es una buena respuesta, gracias. ¿Hay un enlace a donde esta información está 'oficialmente' disponible?
slashmais
1
@slashmais ¿Qué información? La sintaxis del lenguaje de shell está "oficialmente" disponible en varios manuales y especificaciones, pero a partir de ahí para averiguar exactamente qué caracteres necesitan ser citados donde no es completamente sencillo.
Gilles 'SO- deja de ser malvado'
1
También encontré esto: tecmint.com/manage-linux-filenames-with-special-characters : no es tan compacto como su lista, pero tiene muchos ejemplos. (por cierto: "¿Qué información?" no es una respuesta genial cuando el tema aquí se refiere a los personajes)
slashmais