Cómo analizar correctamente los nombres de archivo en Bash

Contenidos

Bash Shell

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'

Configurar un archivo con un carácter CR en el nombre del archivo

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

El problema al tratar de manejar un nombre de archivo que incluye CR

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 '{}|'

Mostrando cómo xargs verá el carácter CR como una nueva línea y dividirá los datos sobre él

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

Todo tipo de caracteres especiales en los nombres de archivo.

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

La solución: encuentra -print0 y xargs -0

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 – el mismo carácter – no visible).

Además notamos que hay un solo CR en la salida, que coincide con el single CR que habíamos ingresado en el primer nombre de archivo, compuesto por a seguido por ingresar seguido por B.

Para terminar, la salida no introduce una nueva línea (que además contiene CR) antes de devolver el $ indicador de terminal, puesto que las cadenas eran NULL y no CR terminado. Pulsamos enter en el $ indicador de terminal para explicar un poco las cosas.

A continuación agregamos xargs con el -0 opciones, lo que posibilita xargs para manejar el NULL terminó la entrada correctamente. Vemos que la entrada pasada y recibida de ls se ve claro y no se produce ninguna alteración de la transformación del texto.

Para terminar volvemos a intentar nuestro rm comando, y esta vez para todos los archivos, incluido el original que contiene el CR con el que tuvimos problemas. los rm funciona estupendamente y no se observan errores ni problemas de análisis. ¡Excelente!

Terminando

Hemos visto cómo es esencial, en varios casos, analizar y manejar correctamente los nombres de archivo en Bash. Mientras que aprender a utilizar find correctamente es un poco más desafiante que simplemente utilizar ls, los beneficios que proporciona pueden dar sus frutos al final. Mayor seguridad y sin problemas con caracteres especiales.

Si disfrutó de este post, es factible que además desee leer Cómo cambiar el nombre de archivos a nombres numéricos de archivos en Linux, que muestra un interesante y algo complejo find -print0 | xargs -0 declaración. ¡Disfrutar!

Suscribite a nuestro Newsletter

No te enviaremos correo SPAM. Lo odiamos tanto como tú.