Я предполагаю, что Вы на самом деле вводите
./myBashScript.sh < text.txt
с наклонной чертой вправо.
Когда Вы работаете ./myBashScript.sh < text.txt
, Ваша интерактивная оболочка на самом деле получает < text.txt
и интерпретирует его как специальную инструкцию – в частности, это интерпретирует Вашу командную строку, чтобы означать, что это должно выполнить myBashScript.sh со стандартным входом, подключенным к text.txt. Ваша оболочка затем удаляет < text.txt
из командной строки перед выдаванием управления к myBashScript.sh. Таким образом, насколько Ваш сценарий оболочки затронут, он получает нулевые аргументы, и $2
пусто. Ваш сценарий переводит просто в
echo
который печатает новую строку.
Если Вы хотите на самом деле распечатать название файла, необходимо рассмотреть
#!/bin/sh
echo $1
который можно затем выполнить:
$ ./myShellScript text.txt
text.txt
Если с другой стороны, Вы хотите распечатать содержание файла, необходимо использовать кошку (1); Ваш сценарий оболочки должен быть
#!/bin/sh
cat $1
который можно затем выполнить:
$ ./myShellScript text.txt
Hello from text.txt, a file containing a bunch of test strings.
Попробуйте:
for x in {a..z} ; do mkdir -p $x/${x}{a..z} ; done
Бэш расширит XXX{a..z}
до XXXa
, XXXb
и так далее. Нет необходимости во внутренней петле, которая у вас есть.
After that:
$ 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
В Perl
:
perl -MFile::Path=make_path -e '
make_path(map { $l=$_; map { "$l/$l$_" } a..z } a..z)
'
Файл::Path
является основным модулем, так как Perl 5.001
.
Итак, с расширением алфавита 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-локации. Так что вы можете сделать установку $(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
Как видите, для
только один раз зацикливается на индекс массива позиционных параметров, который я здесь установил простым передачей sh
параметров при вызове, а выше с помощью установил ${позиции}
. Но printf
получает один и тот же массив в списке аргументов для каждой итерации и применяет строку его формата к каждому аргументу, так что вы получаете подобие рекурсии без лишней рекурсии.
И добавление done|command
будет передавать по цепочке весь вывод цикла для
таким же образом, как done >file
будет передавать все это в файл - только открытие и закрытие выходного файла один раз для всей конструкции для...done
.