Итак, с 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конструкции.