Recorre todos los subdirectorios y haz algo en el script de shell de Unix

17

Quiero que mi script de shell visite todos los subdirectorios en un directorio principal. Haga algo en los directorios, envíe la salida a un archivo de cola y pase al siguiente directorio. Considere Main Dir = / tmp Sub Dir = ABCD (Cuatro subdirectorios)

Ashish
fuente
2
OK, por favor muéstranos tu script hasta ahora. ¿Qué parte de esto te está dando problemas?
terdon

Respuestas:

22

Usa un forbucle:

for d in $(find /path/to/dir -maxdepth 1 -type d)
do
  #Do something, the directory is accessible with $d:
  echo $d
done >output_file

Busca solo los subdirectorios del directorio /path/to/dir. Tenga en cuenta que el ejemplo simple anterior fallará si los nombres de directorio contienen espacios en blanco o caracteres especiales. Un enfoque más seguro es:

find /tmp -maxdepth 1 -type d -print0 |
  while IFS= read -rd '' dir; do echo "$dir"; done

O en claro bash:

for d in /path/to/dir/*; do
  if [ -d "$d" ]; then
    echo "$d"
  fi
done

(tenga en cuenta que, al contrario, findtambién se consideran enlaces simbólicos a directorios y se excluyen los ocultos)

caos
fuente
1
al menos señale las limitaciones y riesgos asociados con el procesamiento de la salida de findese tipo.
Stéphane Chazelas
Hola ... intenté ejecutar a continuación el bucle para d en $ (find / backup / ASHISH -maxdepth 1 -type d) do ls -l | awk '{print $ 9}' | grep CC * _ date +"%m%d20%Y"| xargs echo echo $ d
Ashish
Hola ... Intenté a continuación para el bucle. para d en $ (find / backup / ASHISH -maxdepth 1 -type d) do ls -l | awk '{print $ 9}' | grep CC * _ date +"%m%d20%Y"| xargs echo echo $ d El resultado esperado es ls -ltr de todo el subdirectorio . El bucle anterior no funciona
Ashish
1

Soy un bashnovato completo , pero veterano de UN * X. Aunque indudablemente esto se puede hacer en el script de shell Bash, en los viejos tiempos solíamos find [-maxdepth <levels>] <start-dir> -exec <command> ;lograr esto. ¡Podrías hacer man findy jugar, tal vez hasta que alguien te diga cómo hacerlo bash!

JonBrave
fuente
Estoy muy halagado de que mi respuesta "contorno" aquí ha recibido un up-voto. Sin embargo, ¿por qué tiene respuesta @chaos' por debajo recibido una baja votación? (Como recién llegado a este tablero, no puedo publicar este comentario en contra de su respuesta, sólo contra la mía.) Su segunda sugerencia es correcto para una solución de script de shell, y evita la sobrecarga de la ejecución de un externa findde comando.
JonBrave
Su segundo es de hecho correcto. Su primer fallará si los nombres de directorio contienen espacios en blanco o caracteres especiales (por ejemplo, barras invertidas). Vea la edición que hice a su respuesta para la versión segura.
terdon
Estoy de acuerdo. Era su segunda respuesta, solo concha, que estaba alabando.
JonBrave
Lo sé, solo estaba explicando el voto negativo (que no emití).
terdon
Lo eché. La $(find...)cosa es mala práctica .
Stéphane Chazelas
1

Parece que quiere los nombres de archivo debajo de cada subdirectorio; el ls -l | awkno es lo suficientemente robusta, por lo que si los nombres de archivo contienen espacios en blanco y / o saltos de línea? Lo siguiente findfuncionaría incluso para findaquellos que no tienen la posibilidad de hacerlo -maxdepth:

find . ! -name . -type d -prune -exec sh -c '
   cd "$1" && \
   find "." ! -name . -prune  -type f
' {} {} \;

fuente
0

Tengo la solución El siguiente comando de búsqueda cumple mis requisitos.

find . -maxdepth 1 -type d \( ! -name . \) -exec bash -c "cd '{}' && ls -l |awk '{ print $9 }' |grep `date +"%m%d%Y"`|xargs echo" \;
Ashish
fuente
0

También es posible usar ls, grep y tr

for dir in $(ls -1FA | grep / | tr -d /); do echo $dir/something; done

ls -1FA | grep / | tr -d / | while IFS= read -r TD; do echo $TD/something; done

du / sed también se puede usar como selector si su ls carece de las opciones anteriores

du --max-depth=1 | sed -e 's/^.*\.\///' | grep -v '\.$'

Puede ser importante tener en cuenta que estos ejemplos devuelven directorios ocultos y excluyen directorios principales y actuales

JGurtz
fuente
1
(1)  lsescribe un archivo por línea (lo que -1especifica la opción) de forma predeterminada cuando la salida estándar es una tubería (por lo que es superfluo en sus respuestas). (2) Analizar la salida de lses una mala idea: vea esto y esto . Su primera respuesta fallará si los directorios tienen espacios (o nuevas líneas) en sus nombres, y todos fallarán si tienen nuevas líneas en sus nombres. (3) Siempre debe citar las variables de shell (por ejemplo, "$dir") a menos que tenga una buena razón para no hacerlo y esté seguro de saber lo que está haciendo.
Scott
Buenos puntos Scott. Dejando la respuesta como, para muchos sistemas sin directorios con nombres atroces, creo que aún puede ser útil para los únicos.
JGurtz