Las convenciones de nomenclatura de archivos Bash son muy ricas y es fácil crear un script o una línea que analice incorrectamente los nombres de los archivos. Aprenda a analizar los nombres de los archivos correctamente y, por eso, asegúrese de que sus scripts funcionen según lo previsto.
El problema de analizar correctamente los nombres de archivo en Bash
Si ha estado usando Bash durante un tiempo y ha estado escribiendo en su rico lenguaje Bash, es probable que se haya encontrado con algunos problemas de análisis de nombres de archivos. Echemos un vistazo a un ejemplo simple de lo que puede salir mal:
touch 'a > b'
Aquí creamos un archivo que tiene un CR
(retorno de carro) ingresado en él presionando enter después de la a
. Las convenciones de nomenclatura de archivos Bash son muy ricas, y aún cuando de alguna manera es genial, podemos utilizar caracteres especiales como estos en un nombre de archivo, veamos cómo le va a este archivo cuando intentamos realizar algunas acciones en él:
ls | xargs rm
Eso no funcionó. xargs
tomará la entrada de ls
(a través de el |
tubería) y páselo a rm
, ¡pero algo salió mal en el procedimiento!
Lo que salió mal es que la salida de ls
es tomado literalmente por xargs
, y el ‘entrar’ (CR
– Retorno de carro) dentro del nombre de archivo es visto por xargs
como un personaje de terminación real, no un CR
para ser pasado a rm
como debería ser.
Ejemplifiquemos esto de otra manera:
ls | xargs -I{} echo '{}|'
Está despejado: xargs
está procesando la entrada como dos líneas individuales, dividiendo el nombre del archivo original en dos. Inclusive si tuviéramos que arreglar los problemas de espacio a través de un análisis elegante usando sed, pronto nos encontraríamos con otros problemas cuando empezamos a utilizar otros caracteres especiales como espacios, barras invertidas, comillas y más.
touch 'a b' touch 'a b' touch 'ab' touch 'a"b' touch "a'b" ls
Inclusive si eres un desarrollador experimentado de Bash, es factible que te estremezca al ver nombres de archivo como este, puesto que sería muy complejo, para la mayoría de las herramientas Bash comunes, analizar estos archivos correctamente. Tendría que hacer todo tipo de modificaciones de cadena para que esto funcione. Dicho de otra forma, a menos que tenga la receta secreta.
Antes de sumergirnos en eso, hay una cosa más, algo que debe saber, con la que puede encontrarse al analizar ls
producción. Si utiliza codificación de colores para las listas de directorios, que está habilitada de forma predeterminada en Ubuntu, es fácil ejecutar otro conjunto de ls
problemas de análisis.
Estos no están verdaderamente relacionados con cómo se nombran los archivos, sino más bien con cómo se presentan los archivos como salida de ls
. los ls
la salida contendrá códigos hexadecimales que representan el color que se utilizará en su terminal.
Para evitar encontrarse con estos, simplemente use --color=never
como una opción para ls
:ls --color=never
.
En Mint 20 (un gran sistema operativo derivado de Ubuntu), este problema parece solucionado, aún cuando es factible que el problema aún esté presente en muchas otras versiones de Ubuntu o más antiguas, etc. He visto este problema a mediados de agosto de 2020 en Ubuntu.
Inclusive si no utiliza codificación de colores para sus listados de directorio, es factible que su script se ejecute en otros sistemas que no sean de su propiedad ni sean administrados por usted. En tal caso, además querrá utilizar esta opción para evitar que los usuarios de dicha máquina se ejecuten en el problema descrito.
Volviendo a nuestra receta secreta, veamos cómo podemos asegurarnos de que no tendremos problemas con los caracteres especiales en los nombres de archivo Bash. La respuesta proporcionada evita todo uso de ls
, que haría bien en evitar en general, por lo que los problemas de codificación de colores tampoco son aplicables.
Aún hay momentos en los que ls
El análisis es rápido y práctico, pero siempre será complicado y probablemente ‘sucio’ tan pronto como se introduzcan caracteres especiales, sin mencionar que son inseguros (los caracteres especiales se pueden utilizar para introducir todo tipo de problemas).
La receta secreta: terminación NULA
Los desarrolladores de herramientas Bash se han dado cuenta de este mismo problema muchos años antes y nos han proporcionado: NULL
¡terminación!
Que es NULL
terminación preguntas? Considere cómo en los ejemplos anteriores, CR
(o literalmente ingresar) fue el personaje principal de terminación.
Además vimos cómo se pueden utilizar caracteres especiales como comillas, espacios en blanco y barras invertidas en nombres de archivos, aún cuando disponen funciones especiales cuando se trata de otras herramientas de modificación y análisis de texto Bash como sed. Ahora compare esto con el -0
opción a xargs, de man xargs
:
-0, –nulo Los ítems de entrada terminan con un carácter nulo en lugar de un espacio en blanco, y las comillas y la barra invertida no son especiales (todos los caracteres se toman literalmente). Deshabilita el final de la cadena del archivo, que se trata como cualquier otro argumento. Útil cuando los ítems de entrada pueden contener espacios en blanco, comillas o barras diagonales inversas. La opción GNU find -print0 produce una entrada adecuada para este modo.
Y el -print0
opción a find
, de man find
:
-fprint0 archivo Cierto; imprime el nombre completo del archivo en la salida estándar, seguido de un carácter nulo (en lugar del carácter de nueva línea que utiliza -print). Esto posibilita que los programas que procesan la salida de búsqueda interpreten correctamente los nombres de archivo que contienen nuevas líneas u otros tipos de espacios en blanco. Esta opción corresponde a la opción -0 de xargs.
los Cierto; aquí significa Si se especifica la opción, lo siguiente es verdadero;. Además son interesantes las dos advertencias claras que se dan en otras partes de la misma página de manual:
- Si está canalizando la salida de find a otro programa y existe la mínima oportunidad de que los archivos que está buscando contengan una nueva línea, entonces debería considerar seriamente utilizar la opción -print0 en lugar de -print. Consulte la sección NOMBRES DE ARCHIVO INUSUALES para obtener información acerca de cómo se manejan los caracteres inusuales en los nombres de archivo.
- Si está usando buscar en un script o en una situación en la que los archivos coincidentes pueden tener nombres arbitrarios, debería considerar usar -print0 en lugar de -print.
Estas claras advertencias nos recuerdan que analizar nombres de archivos en bash puede ser, y es, un negocio complicado. A pesar de esto, con las alternativas adecuadas para find
, a saber -print0
, y xargs
, a saber -0
, todos nuestros caracteres especiales que contienen nombres de archivos se pueden analizar correctamente:
ls find . -name 'a*' -print0 find . -name 'a*' -print0 | xargs -0 ls find . -name 'a*' -print0 | xargs -0 rm
Primero revisamos nuestra lista de directorio. Todos nuestros nombres de archivo que contienen caracteres especiales están ahí. A continuación hacemos un simple find ... -print0
para ver la salida. Observamos que las cuerdas son NULL
terminado (con el NULL
o