Создание многочисленных каталогов с использованием mkdir

14

Я хотел бы создать много каталогов, используя mkdir. Каждое имя каталога будет состоять из префикса (строка) и индекса (целое число). Предположим, что я бы хотел, чтобы префикс был «s», а индексы - от 1 до 50. Это означает, что я хотел бы создать каталоги под названием:

s1, s2... s49,,s50

Есть ли способ сделать это автоматически с помощью mkdir? Спасибо за ваше время.

Андрей
источник
2
Какую оболочку вы используете?
Франческо Турко
@FrancescoTurco я использую bash. Спасибо за уделенное время!
Андрей
3
FYI, я считаю , что гораздо полезнее использовать равноширинные индексы, как: s01, s02, ..., s49, s50. Если бы я использовал индексы фиксированной ширины, то /bin/lsпочти всегда создавал нужный мне порядок.
Роб

Ответы:

32

Вы можете сделать это с помощью сценария оболочки.

Pure sh - это будет работать даже на скоропортящихся оболочках POSIX:

n=1;
max=50;
while [ "$n" -le "$max" ]; do
  mkdir "s$n"
  n=`expr "$n" + 1`;
done

Если вы хотите создать большое количество каталогов, вы можете сделать скрипт быстрее, сократив его до одного вызова, mkdirа также используя встроенные функции оболочки для тестирования и арифметики. Как это:

n=1
max=50
set -- # this sets $@ [the argv array] to an empty list.

while [ "$n" -le "$max" ]; do
    set -- "$@" "s$n" # this adds s$n to the end of $@
    n=$(( $n + 1 ));
done 

mkdir "$@"

Zsh, ksh93 или bash делают это намного проще, но я должен отметить, что это не встроено mkdirи может не работать в других оболочках. В более крупных случаях это также может зависеть от ограничений на количество или общий размер аргументов, которые могут быть переданы команде.

mkdir s{1..50}
Random832
источник
3
+1 Это здорово! Я должен придираться к одной вещи: n=$(( n + 1 ))я бы точно так же строго придерживался POSIX и не стоил бы вам недоработки.
Кодзиро
@rahmu [[ключевое слово не POSIX. (Не говоря уже о том , что [ это оболочка встроенный во многих современных оболочках.)
Кодзиро
@kojiro: [[работает на моем ksh88(который предшествует bash), поэтому я предположил, что это был POSIX. Я не смог найти упоминаний об этом в спецификации POSIX, поэтому я верю, что вы правы. Спасибо за информацию!
Рахму
Я думал о добавлении версии с использованием арифметического расширения, но хотел ограничить «чистый sh» вещами, которые работали бы также и с версиями до POSIX. Я также не упомянул seq по той же причине - если у вас есть seq, вы, вероятно, используете bash. Пример цикла также хорош для обхода ограничений аргументов для большего числа каталогов, что также означает, что есть место for i in {range}для пользователей расширенных оболочек.
Random832
Подсказка Zsh в конце удивительна, она сэкономила мне столько времени!
Джейс
33
  • Один

    for i in {1..50}; do
      mkdir s"$i"
    done
  • Два

    mkdir s{1..50}

    Эта опция работает в bash , zsh и ksh93

  • Три

    mkdir $(printf "s%02i " $(seq 1 50))
Jhonathan
источник
4
Зачем тебе использовать один на два?
Кевин
7
Вы можете сделать больше, $iчем просто создать каталог, например mkdir s$i ; echo $i > s$i/$i. Кроме того, One - это хороший, простой пример использования цикла for в bash ... на таком сайте, как этот, совсем не маловероятно, чтобы начинающий пользователь увидел его и подумал: "хорошо, я не осознавал, что вы могли бы сделать это". "---> просветление.
КАС
1
@rahmu Эта функция есть в Bash / Zsh (вероятно, тоже ksh93). Не нужно понижать голос.
helpermethod
3
@rahmu: Я думаю, что стоит подумать, только если ответ Джонатана исправит проблему с оболочкой ОП (bash), а не обязательно с другими.
Франческо Турко
4
@Kevin, хотя вряд ли это будет проблемой для пятидесяти, если у вас есть пятьсот каталогов, чтобы вы могли беспокоиться об ограничениях аргументов.
Random832
10

Здесь много сложных ответов, но bash делает это действительно легко. Конечно, чистое решение POSIX работает, но почему бы не воспользоваться преимуществами используемой bashвами оболочки? Вы можете сделать это легко с расширением скобки :

% mkdir -v s{1..10} && ls -1d s{1..10}                                   (09-24 17:37)
mkdir: created directory `s1'
mkdir: created directory `s2'
mkdir: created directory `s3'
mkdir: created directory `s4'
mkdir: created directory `s5'
mkdir: created directory `s6'
mkdir: created directory `s7'
mkdir: created directory `s8'
mkdir: created directory `s9'
mkdir: created directory `s10'
s1
s10
s2
s3
s4
s5
s6
s7
s8
s9
laebshade
источник
5

mkdir $(seq --format 's%.0f' 1 50)

или если вы хотите числа с нулями (что было бы лучше для сортировки):

mkdir $(seq --format 's%02.0f' 1 50)

или:

mkdir s$(seq -s ' s' -w 1 50)- обратите внимание на строку 's' непосредственно перед $(), без нее первый созданный каталог будет просто '01', а не 's01'

и наконец: mkdir $(printf "s%02i " $(seq 1 50))

seq это от GNU Coreutils

как ни странно, seq --formatили -fопция допускает только двойные типы с плавающей запятой в printf (например, f и g. также странный шестнадцатеричный формат с плавающей запятой, который я никогда не использовал). Понятия не имею почему. Было бы хорошо, если бы он также поддерживал другие printf(3)числовые типы, такие как целое число (d, i), восьмеричное (o, U) или шестнадцатеричное (x, X).

В любом случае, двойной формат с 0 десятичной точностью, например, %.0fили %02.0fдостаточно близок к целому числу для этой цели.

$ seq --help
Использование: seq [OPTION] ... LAST
  или: seq [ОПЦИЯ] ... ПЕРВАЯ ПОСЛЕДНЯЯ
  или: seq [ВАРИАНТ] ... ПЕРВЫЙ ВКЛЮЧЕНО
Печатайте числа от ПЕРВОГО до ПОСЛЕДНЕГО, с шагом ВКЛЮЧЕНИЯ.

  -f, --format = FORMAT использовать FORMAT с плавающей точкой в ​​стиле printf
  -s, --separator = STRING использовать STRING для разделения чисел (по умолчанию: \ n)
  -w, --equal-width выравнивает ширину, дополняя начальными нулями
      --help показать эту справку и выйти
      --version вывести информацию о версии и выйти

Если FIRST или INCREMENT опущены, по умолчанию используется значение 1. То есть
значение параметра INCREMENT по умолчанию равно 1, даже если значение LAST меньше значения FIRST.
FIRST, INCREMENT и LAST интерпретируются как значения с плавающей запятой.
INCREMENT обычно положителен, если FIRST меньше, чем LAST, и
INCREMENT обычно отрицателен, если FIRST больше, чем LAST.
FORMAT должен подходить для печати одного аргумента типа `double ';
по умолчанию используется% .PRECf, если FIRST, INCREMENT и LAST являются фиксированной точкой.
десятичные числа с максимальной точностью PREC и% g в противном случае.

Смотрите также: http://www.gnu.org/software/coreutils/manual/html_node/seq-invocation.html

саз
источник
{1,50}или {01,50}(для заполнения нулями) намного проще и понятнее.
Кевин
1
правда ... если вы используете bash, а не sh. вот почему я проголосовал за ответ @ Random832. это хороший ответ. использование seq также является полезным ответом.
КАС
4

Просто для отличия вот решение POSIX sh, которое использует рекурсию:

makedirs() {
  [ "$1" -gt 0 ] || return
  mkdir "s$1"
  makedirs $(( $1 - 1 ))
}
$ makedirs 9
$ ls
s1  s2  s3  s4  s5  s6  s7  s8  s9
Кодзиро
источник