Crear recursivamente directorios para todas las letras

12

Quiero crear un directorio de tal manera que necesite etiquetar los directorios de aa z. Dentro de cada uno de estos directorios, necesito crear subdirectorios para que estén etiquetados como aa, abetc.

Entonces, por ejemplo, para el directorio m, mis subdirectorios se etiquetarán como ma, mbhasta mz.

Ramesh
fuente
3
no necesita el primer mkdir porque -p también está creando los subdirectorios. Y no necesita el comando cd si usa abolir rutas. De lo contrario, es agradable, funciona, las variables declaradas, etc. La versión de Michael Homer es más corta y quizás tenga un mejor rendimiento, pero para una tarea tan simple la suya sería lo suficientemente buena.
1
En el pasado había más entradas de termininfo y no había una sintaxis bash {a..z}, así que enumeraría /usr/share/terminfocon [az] y usaría esa salida. Linux es bastante escaso en ese aspecto, solía ser entradas para todos los caracteres en mayúsculas y minúsculas más los dígitos.
esquemas

Respuestas:

19

Tratar:

for x in {a..z} ; do mkdir -p $x/${x}{a..z} ; done

Bash se expandirá XXX{a..z}a XXXa, XXXby así sucesivamente. No hay necesidad del bucle interno que tienes.

Después de esto:

$ ls
a  b  c  d  e  f  g  h  i  j  k  l  m  n  o  p  q  r  s  t  u  v  w  x  y  z
$ ls m
ma  mc  me  mg  mi  mk  mm  mo  mq  ms  mu  mw  my
mb  md  mf  mh  mj  ml  mn  mp  mr  mt  mv  mx  mz
Michael Homer
fuente
7

Entonces, con bashla expansión del alfabeto, esto funciona:

set {a..z}
for a do printf "./$a/$a%s\n" "$@"
done | xargs mkdir -p

Y si solo escribe el alfabeto una vez en la primera línea, el mismo concepto debería ser portátil para cualquier shell. Hay otras formas de llegar a la línea establecida si no desea escribirla como:

seq -sP32P 97 123|dc
a b c d e f g h i j k l m n o p q r s t u v w x y z 

... por ejemplo, funciona en un entorno local ASCII. Por lo tanto, podría hacer set $(seq -sP32P 97 123|dc)o cualquier otro comando que le proporcionaría una $IFSlista separada de los argumentos que necesita, pero, quiero decir, probablemente sea mejor usar la bashcosa o escribirla.

De todos modos, creo que esa es la forma en que lo haría solo porque solo invoca mkdircon la frecuencia necesaria.

Y solo para demostrar cómo funciona, aquí hay una pequeña salida de depuración de un conjunto más pequeño:

sh -cx 'for n do printf "./$n/$n%s\n" "$@"; done|cat' -- arg1 arg2 arg3
+ for n in '"$@"'
+ printf './arg1/arg1%s\n' arg1 arg2 arg3
+ cat
+ for n in '"$@"'
+ printf './arg2/arg2%s\n' arg1 arg2 arg3
+ for n in '"$@"'
+ printf './arg3/arg3%s\n' arg1 arg2 arg3
./arg1/arg1arg1
./arg1/arg1arg2
./arg1/arg1arg3
./arg2/arg2arg1
./arg2/arg2arg2
./arg2/arg2arg3
./arg3/arg3arg1
./arg3/arg3arg2
./arg3/arg3arg3

Como puede ver, los forúnicos bucles una vez por índice de matriz de parámetros posicionales, que establezco aquí simplemente entregando shlos parámetros en la invocación, y arriba con set ${positionals}. Pero printfrecibe la misma matriz en su lista de argumentos para cada iteración y aplica su cadena de formato a cada uno de sus argumentos, por lo que obtiene la apariencia de recursión sin ninguna recursión innecesaria.

Y agregar el done|commandflujo de transmisión de toda forla salida de un bucle sobre la tubería de la misma manera done >filelo transmitiría todo en un archivo, solo abriendo y cerrando el archivo de salida una vez para toda la for...doneconstrucción.

mikeserv
fuente
3

A partir de aquí , terminé creando un script como este. Sin embargo, si obtengo una solución elegante, la aceptaré como respuesta.

for x in {a..z}
do
    mkdir -p /home/ramesh/$x
    cd /home/ramesh/$x
    for y in {a..z}
    do
        mkdir -p /home/ramesh/$x/$x$y
    done
done
Ramesh
fuente
+1, buena pregunta y mejor respuesta :)
Nidal
@Networker, estoy seguro de que hay una solución bastante buena que esta. Esperando una respuesta experta que haga el trabajo tan similar a esta respuesta, pero se verá mucho mejor :)
Ramesh
Estrictamente hablando, no es necesario cuando se sabe cuáles serán los valores de las variables (y son cadenas simples), pero es una buena idea acostumbrarse a citar sus variables. Podrías usar /home/ramesh/"$x"/"$x$y", /home/ramesh/"$x/$x$y"o "/home/ramesh/$x/$x$y"- todos son equivalentes.
Scott
1

En Perl:

perl -MFile::Path=make_path -e '
    make_path(map { $l=$_; map { "$l/$l$_" } a..z } a..z)
'

File::Pathes módulo central desde entonces Perl 5.001.

Cuonglm
fuente