Рекурсивно створюйте каталоги для всіх листів


12

Я хочу створити каталог таким чином, що мені потрібно мітити каталоги від aдо z. Усередині кожного з цих каталогів, мені потрібно створити підкаталоги так , щоб вони позначені як aa, і abт.д.

Так, наприклад, для каталогу m, мої підкаталоги будуть позначені як ma, mbupto mz.


3
вам не потрібен перший mkdir, оскільки -p теж створює підкаталоги. І вам не потрібна команда cd, якщо ви використовуєте відміняти шляхи. Інакше це приємно, працює, декларуються змінні тощо. Версія Майкла Гомера коротша і, можливо, має кращу ефективність, але для такого простого завдання ваше було б досить добре.

1
Ще в той день було більше записів у терміналі та немає синтаксису 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конструкції.


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, гарне запитання та краща відповідь :)
Nidal

@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.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.