GNU/Linux >> Tutoriales Linux >  >> Linux

¿Por qué el bucle sobre la salida de Find es una mala práctica?

Esta pregunta está inspirada en

¿Por qué se considera una mala práctica usar un bucle de shell para procesar texto?

Veo estas construcciones

for file in `find . -type f -name ...`; do smth with ${file}; done

y

for dir in $(find . -type d -name ...); do smth with ${dir}; done

siendo utilizado aquí casi a diario, incluso si algunas personas se toman el tiempo para comentar esas publicaciones explicando por qué este tipo de cosas deben evitarse...
Al ver la cantidad de tales publicaciones (y el hecho de que a veces esos comentarios son simplemente ignorado) Pensé que también podría hacer una pregunta:

¿Por qué se repite find? La mala práctica de salida y cuál es la forma correcta de ejecutar uno o más comandos para cada nombre de archivo/ruta devuelto por find ?

Respuesta aceptada:

El problema

for f in $(find .)

combina dos cosas incompatibles.

find imprime una lista de rutas de archivo delimitadas por caracteres de nueva línea. Mientras que el operador split+glob que se invoca cuando deja ese $(find .) sin comillas en ese contexto de lista lo divide en los caracteres de $IFS (por defecto incluye nueva línea, pero también espacio y tabulación (y NUL en zsh )) y realiza globbing en cada palabra resultante (excepto en zsh ) (¡e incluso expansión de llaves en derivados de ksh93 o pdksh!).

Incluso si lo logras:

IFS='
' # split on newline only
set -o noglob # disable glob (also disables brace expansion in pdksh
              # but not ksh93)
for f in $(find .) # invoke split+glob

Eso sigue siendo incorrecto ya que el carácter de nueva línea es tan válido como cualquier otro en una ruta de archivo. La salida de find -print simplemente no es posprocesable de manera confiable (excepto mediante el uso de algún truco intrincado, como se muestra aquí ).

Eso también significa que el shell necesita almacenar la salida de find completamente, y luego dividirlo+globarlo (lo que implica almacenar esa salida por segunda vez en la memoria) antes de comenzar a recorrer los archivos.

Tenga en cuenta que find . | xargs cmd tiene problemas similares (allí, espacios en blanco, nueva línea, comillas simples, comillas dobles y barra invertida (y con algo de xarg bytes de implementaciones que no forman parte de caracteres válidos) son un problema)

Más alternativas correctas

La única forma de usar un for bucle en la salida de find sería usar zsh que soporta IFS=$'

Linux
  1. Ssh - ¿Por qué Firefox es tan lento sobre Ssh?

  2. ¿Por qué Grep -o -w no me da la salida esperada en Mac Os X?

  3. ¿Cómo recorrer directorios en Linux?

  4. Iterando sobre cada línea de salida ls -l

  5. Iterar sobre una lista de archivos con espacios

¿Por qué no 'encuentra' Mostrar este archivo?

¿Por qué `less` no muestra la salida en negrita?

¿Por qué sale esta canalización de shell?

Linux, ¿por qué no puedo canalizar el resultado de búsqueda a rm?

¿Por qué es tan difícil encontrar un archivo en Ubuntu?

¿Sudo su - se considera una mala práctica?