Cómo recorrer un árbol de directorios en Linux

Computadora portátil Linux que muestra un indicador de bash
fatmawati achmad zaenuri/Shutterstock.com

Los directorios en Linux le permiten agrupar archivos en colecciones distintas y separadas. La desventaja es que se vuelve tedioso moverse de un directorio a otro para realizar una tarea repetitiva. Aquí se explica cómo automatizar eso.

Todo sobre directorios

El primer comando que aprende cuando se le presenta Linux es probablemente lspero cd no se quedará atrás. Comprender los directorios y cómo moverse por ellos, particularmente los subdirectorios anidados, es una parte fundamental para comprender cómo se organiza Linux y cómo puede organizar su propio trabajo en archivos, directorios y subdirectorios.

Comprender el concepto de un árbol de directorios, y cómo moverse entre ellos, es uno de los muchos pequeños hitos que supera a medida que se familiariza con el panorama de Linux. Usando cd con una ruta te lleva a ese directorio. Atajos como cd ~ o cd por sí solo lo llevará de regreso a su directorio de inicio, y cd .. lo sube un nivel en el árbol de directorios. Simple.

Sin embargo, no existe un medio igualmente simple de ejecutar un comando en todos los directorios de un árbol de directorios. Hay diferentes formas en que podemos lograr esa funcionalidad, pero no hay un comando estándar de Linux dedicado a ese propósito.

Algunos comandos, como lstienen opciones de línea de comandos que los obligan a operar recursivamente, lo que significa que comienzan en un directorio y trabajan metódicamente a través de todo el árbol de directorios debajo de ese directorio. Para lses el -R opción (recursiva).

Si necesita usar un comando que no admite la recursividad, debe proporcionar la funcionalidad recursiva usted mismo. Así es como se hace.

RELACIONADO: 37 comandos importantes de Linux que debe conocer

El comando del árbol

los tree El comando no nos ayudará con la tarea en cuestión, pero facilita ver la estructura de un árbol de directorios. Dibuja el árbol en una ventana de terminal para que podamos obtener una visión general instantánea de los directorios y subdirectorios que componen el árbol de directorios y sus posiciones relativas en el árbol.

Tendrás que instalar tree .

En Ubuntu necesitas escribir:

sudo apt install tree

Instalando árbol en Ubuntu

En Fedora, use:

sudo dnf install tree

Instalando árbol en Fedora

En Manjaro, el comando es:

sudo pacman -Sy tree

Instalación de árbol en Manjaro

Usando tree sin parámetros dibuja el árbol debajo del directorio actual.

tree

Árbol en ejecución en el directorio actual

Puedes pasar un camino a tree en la línea de comando.

tree work

Árbol en ejecución en un directorio especificado

los -d La opción (directorios) excluye archivos y solo muestra directorios.

tree -d work

Ejecutar árbol y solo mostrar directorios

Esta es la forma más conveniente de obtener una vista clara de la estructura de un árbol de directorios. El árbol de directorios que se muestra aquí es el que se utiliza en los siguientes ejemplos. Hay cinco archivos de texto y ocho directorios.

No analice la salida de ls a directorios transversales

Su primer pensamiento podría ser, si ls puede recorrer recursivamente un árbol de directorios, ¿por qué no usar ls hacer exactamente eso y canalizar la salida a otros comandos que analizan los directorios y realizan algunas acciones?

Analizando la salida de ls se considera una mala práctica. Debido a la capacidad de Linux para crear nombres de archivos y directorios que contengan todo tipo de caracteres extraños, se vuelve muy difícil crear un analizador genérico universalmente correcto.

Es posible que nunca cree a sabiendas un nombre de directorio tan absurdo como este, pero un error en una secuencia de comandos o una aplicación podría hacerlo.

Un nombre de directorio extraño

El análisis de nombres de archivos y directorios legítimos pero mal considerados es propenso a errores. Hay otros métodos que podemos usar que son más seguros y mucho más robustos que confiar en la interpretación de la salida de ls.

Usando el comando de búsqueda

los find El comando tiene capacidades recursivas incorporadas y también tiene la capacidad de ejecutar comandos por nosotros. Esto nos permite construir poderosas frases ingeniosas. Si es algo que probablemente quiera usar en el futuro, puede convertir su frase de una sola línea en un alias o una función de shell.

Este comando recorre recursivamente el árbol de directorios, buscando directorios. Cada vez que encuentra un directorio, imprime el nombre del directorio y repite la búsqueda dentro de ese directorio. Habiendo completado la búsqueda en un directorio, sale de ese directorio y reanuda la búsqueda en su directorio principal.

find work -type d -execdir echo "In:" {} ;

usando el comando find para buscar directorios recursivamente

Puede ver por el orden en que se enumeran los directorios, cómo avanza la búsqueda a través del árbol. Al comparar la salida del tree comando a la salida del find de una sola línea, verás cómo find busca en cada directorio y subdirectorio a su vez hasta que llega a un directorio sin subdirectorios. Luego vuelve a subir un nivel y reanuda la búsqueda en ese nivel.

Así es como se compone el comando.

  • encontrar: Los find dominio.
  • trabajar: El directorio para iniciar la búsqueda. Puede ser una ruta.
  • -tipo d: Estamos buscando directorios.
  • -ejecdir: Vamos a ejecutar un comando en cada directorio que encontremos.
  • eco «En:» {}: Este es el comando. Simplemente estamos haciendo eco del nombre del directorio en la ventana de la terminal. El «{}» contiene el nombre del directorio actual.
  • ;: Este es un punto y coma que se usa para terminar el comando. Necesitamos escapar con la barra invertida para que Bash no lo interprete directamente.

Con un ligero cambio, podemos hacer que el comando de búsqueda devuelva archivos que coincidan con una pista de búsqueda. Necesitamos incluir la opción -name y una pista de búsqueda. En este ejemplo, buscamos archivos de texto que coincidan con «*.txt» y hacemos eco de su nombre en la ventana de la terminal.

find work -name "*.txt" -type f -execdir echo "Found:" {} ;

usando el comando find para encontrar archivos recursivamente

Ya sea que busque archivos o directorios, depende de lo que quiera lograr. Para ejecutar un comando dentro de cada directoriousar -type d . Para ejecutar un comando en cada archivo coincidenteusar -type f.

Este comando cuenta las líneas en todos los archivos de texto en el directorio y subdirectorios de inicio.

find work -name "*.txt" -type f -execdir wc -l {} ;

Usando find con el comando wc

RELACIONADO: Cómo usar el comando de búsqueda en Linux

Recorriendo árboles de directorios con un script

Si necesita recorrer directorios dentro de un script, puede usar el find comando dentro de su script. Si necesita, o simplemente desea, realizar las búsquedas recursivas usted mismo, también puede hacerlo.

#!/bin/bash

shopt -s dotglob nullglob

function recursive {

  local current_dir dir_or_file

  for current_dir in $1; do

    echo "Directory command for:" $current_dir

    for dir_or_file in "$current_dir"/*; do

      if [[ -d $dir_or_file ]]; then
        recursive "$dir_or_file"
      else
        wc $dir_or_file
      fi
    done
  done
}

recursive "$1"

Copie el texto en un editor y guárdelo como «recurse.sh», luego use el chmod comando para hacerlo ejecutable.

chmod +x recurse.sh

Hacer que el script recurse.sh sea ejecutable

El script establece dos opciones de shell, dotglob y nullglob.

los dotglob configuración significa nombres de archivos y directorios que comienzan con un punto “.” se devolverá cuando se expandan los términos de búsqueda con comodines. Esto significa que estamos incluyendo archivos y directorios ocultos en nuestros resultados de búsqueda.

los nullglob la configuración significa que los patrones de búsqueda que no encuentran ningún resultado se tratan como una cadena vacía o nula. No tienen como valor predeterminado el término de búsqueda en sí. En otras palabras, si estamos buscando todo en un directorio usando el comodín asterisco “*“, pero no hay resultados, recibiremos una cadena nula en lugar de una cadena que contiene un asterisco. Esto evita que la secuencia de comandos intente abrir un directorio llamado «*» o trate «*» como un nombre de archivo.

A continuación, define una función llamada recursive. Aquí es donde suceden las cosas interesantes.

Se declaran dos variables, llamadas current_dir y dir_or_file . Estas son variables locales, y solo pueden ser referenciadas dentro de la función.

Una variable llamada $1 también se utiliza dentro de la función. Este es el primer (y único) parámetro que se pasa a la función cuando se llama.

El guión utiliza dos for bucles, uno anidado dentro del otro. El primero (exterior) for loop se usa para dos cosas.

Una es ejecutar cualquier comando que desee ejecutar en cada directorio. Todo lo que estamos haciendo aquí es hacer eco del nombre del directorio en la ventana de la terminal. Por supuesto, podría usar cualquier comando o secuencia de comandos, o llamar a otra función de script.

La segunda cosa que hace el bucle for externo es verificar todos los objetos del sistema de archivos que puede encontrar, que serán archivos o directorios. Este es el propósito del interior. for círculo. A su vez, cada nombre de archivo o directorio se pasa al dir_or_file variable.

los dir_or_file Luego, la variable se prueba en una declaración if para ver si es un directorio.

  • Si es así, la función se llama a sí misma y pasa el nombre del directorio como parámetro.
  • Si el dir_or_file variable no es un directorio, entonces debe ser un archivo. Cualquier comando que desee que se aplique al archivo se puede llamar desde el else cláusula de la if declaración. También puede llamar a otra función dentro del mismo script.

La línea final en el script llama al recursive función y pasa en la primera línea de comando parámetro $1 como el directorio de inicio para buscar. Esto es lo que inicia todo el proceso.

Ejecutemos el script.

./recurse.sh work

Procesando los directorios desde el más superficial al más profundo

Los directorios se recorren, y el punto en el script donde se ejecutaría un comando en cada directorio se indica mediante las líneas «Directorio comando para:». Los archivos que se encuentran tienen la wc ejecutar el comando en ellos para contar líneas, palabras y caracteres.

El primer directorio procesado es «trabajo», seguido de cada rama de directorio anidado del árbol.

Un punto interesante a tener en cuenta es que puede cambiar el orden en que se procesan los directorios, moviendo los comandos específicos del directorio de estar encima del bucle for interno a estar debajo de él.

Vamos a mover la línea «Directorio comando para:» después de la done del interior for círculo.

#!/bin/bash

shopt -s dotglob nullglob

function recursive {

  local current_dir dir_or_file

  for current_dir in $1; do

    for dir_or_file in "$current_dir"/*; do

      if [[ -d $dir_or_file ]]; then
        recursive "$dir_or_file"
      else
        wc $dir_or_file
      fi

    done

    echo "Directory command for:" $current_dir

  done
}

recursive "$1"

Ahora ejecutaremos el script una vez más.

./recurse.sh work

Procesando los directorios de más profundo a más superficial

Esta vez, los directorios tienen los comandos aplicados primero desde los niveles más profundos, trabajando de regreso a las ramas del árbol. El directorio pasado como parámetro al script se procesa en último lugar.

Si es importante procesar primero los directorios más profundos, así es como puede hacerlo.

La recursividad es rara

Es como llamarte a ti mismo a tu propio teléfono y dejarte un mensaje para decirte la próxima vez que te encuentres, repetidamente.

Puede tomar un poco de esfuerzo antes de que capte sus beneficios, pero cuando lo haga, verá que es una forma programáticamente elegante de abordar problemas difíciles.

RELACIONADO: ¿Qué es la recursividad en la programación y cómo se usa?

Deja un comentario

En esta web usamos cookies para personalizar tu experiencia de usuario.    Política de cookies
Privacidad