Cria recursivamente diretórios para todas as letras

12

Eu quero criar um diretório de forma que eu precise rotular os diretórios de a para z . Dentro de cada um desses diretórios, eu preciso criar subdiretórios para que eles sejam rotulados como aa , ab etc.

Assim, por exemplo, para o diretório m , meus subdiretórios serão rotulados como ma , mb até mz .

    
por Ramesh 22.07.2014 / 01:30

4 respostas

19

Tente:

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

O Bash expandirá XXX{a..z} para XXXa , XXXb e assim por diante. Não há necessidade do loop interno que você tem.

Depois disso:

$ 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
    
por 22.07.2014 / 01:34
7

Portanto, com a expansão do alfabeto de bash , isso funciona:

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

E se você digitar o alfabeto uma vez na primeira linha, o mesmo conceito deve ser portável para qualquer shell. Existem outras maneiras de chegar ao set line se você não quiser digitá-lo 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 exemplo, funciona em uma localidade ASCII. Então você poderia fazer set $(seq -sP32P 97 123|dc) ou qualquer outro comando que pudesse te dar uma lista separada por $IFS dos argumentos que você precisa, mas, provavelmente, é melhor apenas usar a bash thing ou digitar ela.

De qualquer forma, acho que é assim que eu faria apenas porque ele invoca mkdir sempre que necessário.

E apenas para demonstrar como funciona, aqui está uma pequena saída de depuração de um conjunto menor:

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 você pode ver, o for só faz um loop uma vez por índice de matriz de parâmetro posicional, que definimos aqui simplesmente entregando sh os parâmetros na chamada e acima com set ${positionals} . Mas printf recebe o mesmo array em sua lista de argumentos para cada iteração e aplica sua string de formato a cada um de seus argumentos, assim você obtém a aparência de recursão sem qualquer recursão desnecessária.

E adicionar o done|command transmitirá toda a saída de for do loop pelo canal da mesma maneira que done >file transmitirá tudo em um arquivo - apenas abrindo e fechando o arquivo de saída uma vez para todo o for...done de construção.

    
por 22.07.2014 / 07:12
3

De aqui , acabei criando um script como este. No entanto, se eu obtiver uma solução elegante, aceitarei isso como uma resposta.

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
    
por 22.07.2014 / 01:30
1

Em Perl :

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

File::Path é o módulo principal desde Perl 5.001 .

    
por 22.07.2014 / 20:35