рекурсивный MKDIR


307

Есть ли команда Linux, которую я пропускаю, которая позволяет сделать что-то вроде: (псевдо)

$ mkdir -R foo/bar/zoo/andsoforth

Или нет другого выхода, кроме как делать каталоги по одному?



1
Забавно, я смотрел на эту страницу, но полностью игнорировал «родителей», потому что думал о них как о детях (слева направо).

18
Подсказка: в некоторых снарядах вы даже можете mkdir -p foo/{bar,baz}/zoo/andsoforth. Очень полезно!
Аарон Копли

1
Лично я также упустил из виду «родителя» на странице руководства, потому что я чувствую, что флаг должен быть «-r» для «рекурсивного» - или, по крайней мере, должен быть псевдоним для такого, так как mkdirимеет только 6 Всего задокументированных флагов. Черт, я чувствую, что команда должна рекурсивно создавать каталоги по умолчанию, и если вы не хотите этого, вам следует указать это явно.
Jbowman

Ответы:


514
$ mkdir -p foo/bar/zoo/andsoforth

93
К вашему сведению -p означает «родители»
Карл Кротт

14
Вместо этого они могли бы сделать -r, как и любую другую команду, невозможно запомнить конкретные параметры для каждой команды linux
Vedmant

2
Но mkdir -pне кроссплатформенный, не работает в каждой оболочке
Роман Коптев

9
@ РоманКоптев, mkdir -pкак указано в стандарте POSIX , который ближе всего к тому , полностью портативный. Что лучше вы ожидаете в сценарии оболочки?
Wildcard

5
@StephanBijzitter Да, это unix.se, а не unixandwindows.se. :)
EEAA

16

Использованиеmkdir -p - это простой способ для большинства современных ОС:

mkdir -p foo/bar/zoo/andsoforth

Однако mkdir -pне рекомендуется во многих руководствах. Прочтите документацию по GNU makeи autoconfо проблемах с использованием mkdir -p:

Кроссплатформенные системы установки и настройки имеют свои собственные безопасные альтернативыmkdir -p .

CMake для использования в командной строке оболочки:

 cmake -E make_directory foo/bar/zoo/andsoforth

Autoconf для использования в скрипте с предварительной обработкой:

AS_MKDIR_P(foo/bar/zoo/andsoforth)

или же:

AC_PROG_MKDIR_P(foo/bar/zoo/andsoforth)

Но эти решения требуют cmakeили autoconf( M4) инструментов для установки (и возможной предварительной обработки)

Вы также можете использовать install-shскрипт с -dопцией:

install-sh -d foo/bar/zoo/andsoforth

Этот скрипт используется autoconfи automakeпроекта. Я думаю, что это должно быть самым безопасным решением.

В то время я искал кроссплатформенное решение для стандарта /bin/shбез зависимостей, но не нашел его. Поэтому я написал следующий скрипт, который может быть не идеальным, но я думаю, что он соответствует большинству кроссплатформенных требований :

#! /bin/sh

cdirname() # cross platform alternative for 'dirname'
{
  # $1 - path
  test $# -eq 1 || { echo "Procedure 'cdirname' must have only one parameter. Scripting error."; exit 1; }
  echo "$1" | sed -n -e '1p' | sed  -e 's#//*#/#g' -e 's#\(.\)/$#\1#' -e 's#^[^/]*$#.#' -e 's#\(.\)/[^/]*$#\1#' -
}

mkd() # cross platform alternative for 'mkdir -p'
{
  # $1 - directory to create
  test $# -eq 1 || { echo "Function 'mkd' can create only one directory (with it's parent directories)."; exit 1; }
  test -d "$1"  && return 0
  test -d "$(cdirname "$1")" || { mkd "$(cdirname "$1")" || return 1; }
  test -d "$1" || { mkdir "$1" || return 1; }
  return 0
}

Этот скрипт можно использовать для старых систем, где опция -pfor mkdirотсутствует.

sedкросс-платформенная версия dirnameбыла добавлена ​​в код. Он работает аналогично dirname(корректно с путем /, путями только с базовым именем, путями с завершающими /, путями с и без конечных \ns). Эта функция не может работать корректно, если путь содержит новые строки или некоторые недопустимые символы для текущей локали. Он также заменяет любую комбинацию /( //, ///)/

Изменена строка mkdir "$1" || return 1на test -d "$1" || { mkdir "$1" || return 1; }потому что mkdirзавершается с ошибкой, если путь существует, и эта проверка необходима для путей, содержащих конструкции, такие как aaa\.(Если aaaне существует, предыдущая версия создает, aaaа затем пытается создать ее снова).

Эта версия mkd не генерирует ошибку, если путь уже существует (но у нее все еще есть возможность генерировать такую ​​ошибку при параллельном выполнении) и не может получить несколько каталогов в командной строке.


4
«mkdir -p» определяется posix. Какие unix или unix-подобные варианты не поддерживают это? (и это не должно быть встроенной оболочкой, хотя я думаю, что нет никаких причин, по которым это не может быть.) pubs.opengroup.org/onlinepubs/9699919799/utilities/mkdir.html
Тим Б

5
Некоторой информации на этой странице всего 15 лет. Некоторые старше.
Томас Дики

7
Системы, которые не будут поддерживать mkdir -p, будут слишком старыми (а мы говорим, по крайней мере, пару десятилетий), чтобы иметь printfутилиту или поддержку --для обозначения конца опций.
Стефан Шазелас

2
Вы cdirnameбы дали неправильный ответ foo/bar//, или имена каталогов, содержащие символы новой строки, или недопустимые символы в текущей локали.
Стефан Шазелас

2
printfбезопасен в системах POSIX. Поддержка систем POSIX mkdir -p. mkdir -pбыл определен POSIX на протяжении десятилетий. --начал широко распространяться в системах AT & T, начиная с SysIII, в начале середины 80-х годов. printfсначала появился как kshвстроенный, я считаю, и был определен POSIX позже, чем mkdir -p. Некоторые оболочки POSIX (например, основанные на pdksh или yash) по-прежнему не имеют printfвстроенных функций.
Стефан Шазелас

0

Опция -pв команде mkdirделает р ARENT каталогов , как не требуется (нет ошибки , если таковые имеются):

mkdir -p foo/bar/zoo/andsoforth

Другой способ, например, использовать &&(ошибка, если указанная папка существует):

mkdir foo && mkdir foo/bar && mkdir foo/bar/zoo && mkdir foo/bar/zoo/andsoforth

Оператор цепочки &&используется для объединения команд таким образом, что следующая команда выполняется тогда и только тогда, когда предыдущая команда завершилась без ошибок.

Конечно, первый способ лучше.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.