Рекурсивно создавать каталоги для всех писем

12

Я хочу создать каталог таким образом, чтобы мне нужно было пометить каталоги из aв z. Внутри каждого из этих каталогов мне нужно создать подкаталоги, чтобы они были помечены как aaи abт. Д.

Так, например, для каталога m, мои подкаталоги будут помечены как ma, mbДО mz.

Рамеш
источник
3
вам не нужен первый mkdir, потому что -p также создает подкаталоги. И вам не нужна команда cd, если вы используете абсолютные пути. В противном случае это хорошо, работает, объявлены переменные и т. Д. Версия Майкла Гомера короче и, возможно, имеет лучшую производительность, но для такой простой задачи ваша будет достаточно хорошей.
1
Раньше было больше записей termininfo и нет синтаксиса bash {a..z}, поэтому я бы перечислил с /usr/share/terminfoпомощью [az] и использовал этот вывод. В этом отношении Linux довольно немногочисленна: раньше это были записи для всех прописных и строчных букв, а также цифр.
схемы

Ответы:

19

Пытаться:

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

Bash будет расширяться XXX{a..z}, чтобы XXXa, XXXbи так далее. Там нет необходимости для внутреннего цикла у вас есть.

После того:

$ 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
Майкл Гомер
источник
7

Итак, с bashрасширением алфавита, это работает:

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

И если вы просто набираете алфавит один раз в первой строке, то такая же концепция должна переноситься на любую оболочку. Есть и другие способы добраться до заданной строки, если вы не хотите печатать ее так:

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 

... например, работает в ASCII локали. Таким образом, вы можете выполнить set $(seq -sP32P 97 123|dc)или любую другую команду, которая выдаст вам $IFSотдельный список аргументов, которые вам нужны, но, я имею в виду, вероятно, лучше просто использовать bashвещь или набрать ее.

Во всяком случае, я думаю, что я бы так поступил, хотя бы потому, что он вызывается mkdirтак часто, как это необходимо.

И просто чтобы продемонстрировать, как это работает, вот небольшой отладочный вывод меньшего набора:

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

Как вы можете видеть, forединственные циклы один раз на индекс массива позиционных параметров, которые я здесь устанавливаю, просто передавая shпараметры при вызове и выше с помощью set ${positionals}. Но printfполучает один и тот же массив в своем списке аргументов для каждой итерации и применяет свою строку формата к каждому из своих аргументов, так что вы получаете видимость рекурсии без какой-либо ненужной рекурсии.

А добавление done|commandволи к потоку всех forвыходных данных цикла по каналу таким же образом done >fileприведет к тому, что все это будет передано в файл - только один раз открывая и закрывая выходной файл для всей for...doneконструкции.

mikeserv
источник
3

Из здесь , я в конечном итоге создание сценария , как это. Однако, если я получу элегантное решение, я приму его в качестве ответа.

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
Рамеш
источник
+1, хороший вопрос и лучший ответ :)
Нидаль
@ Networker, я уверен, что есть хорошее решение, чем это. В ожидании какого-то экспертного ответа, который сделает работу такой же, как этот ответ, но будет выглядеть намного круче :)
Рамеш
Строго говоря, это не обязательно, когда вы знаете, какими будут значения переменных (и они являются простыми строками), но это хорошая идея, чтобы привыкнуть заключать в кавычки ваши переменные. Вы можете использовать /home/ramesh/"$x"/"$x$y", /home/ramesh/"$x/$x$y"или ... "/home/ramesh/$x/$x$y"они все эквивалентны.
Скотт
1

В Perl:

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

File::Pathявляется основным модулем так Perl 5.001.

cuonglm
источник