Забавно, я смотрел на эту страницу, но полностью игнорировал «родителей», потому что думал о них как о детях (слева направо).
18
Подсказка: в некоторых снарядах вы даже можете mkdir -p foo/{bar,baz}/zoo/andsoforth. Очень полезно!
Аарон Копли
1
Лично я также упустил из виду «родителя» на странице руководства, потому что я чувствую, что флаг должен быть «-r» для «рекурсивного» - или, по крайней мере, должен быть псевдоним для такого, так как mkdirимеет только 6 Всего задокументированных флагов. Черт, я чувствую, что команда должна рекурсивно создавать каталоги по умолчанию, и если вы не хотите этого, вам следует указать это явно.
Кроссплатформенные системы установки и настройки имеют свои собственные безопасные альтернативы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 не генерирует ошибку, если путь уже существует (но у нее все еще есть возможность генерировать такую ошибку при параллельном выполнении) и не может получить несколько каталогов в командной строке.
«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 -p foo/{bar,baz}/zoo/andsoforth
. Очень полезно!mkdir
имеет только 6 Всего задокументированных флагов. Черт, я чувствую, что команда должна рекурсивно создавать каталоги по умолчанию, и если вы не хотите этого, вам следует указать это явно.Ответы:
источник
mkdir -p
не кроссплатформенный, не работает в каждой оболочкеmkdir -p
как указано в стандарте POSIX , который ближе всего к тому , полностью портативный. Что лучше вы ожидаете в сценарии оболочки?Использование
mkdir -p
- это простой способ для большинства современных ОС:Однако
mkdir -p
не рекомендуется во многих руководствах. Прочтите документацию по GNUmake
иautoconf
о проблемах с использованиемmkdir -p
:Кроссплатформенные системы установки и настройки имеют свои собственные безопасные альтернативы
mkdir -p
.CMake для использования в командной строке оболочки:
Autoconf для использования в скрипте с предварительной обработкой:
или же:
Но эти решения требуют
cmake
илиautoconf
(M4
) инструментов для установки (и возможной предварительной обработки)Вы также можете использовать
install-sh
скрипт с-d
опцией:Этот скрипт используется
autoconf
иautomake
проекта. Я думаю, что это должно быть самым безопасным решением.В то время я искал кроссплатформенное решение для стандарта
/bin/sh
без зависимостей, но не нашел его. Поэтому я написал следующий скрипт, который может быть не идеальным, но я думаю, что он соответствует большинству кроссплатформенных требований :Этот скрипт можно использовать для старых систем, где опция
-p
formkdir
отсутствует.sed
кросс-платформенная версияdirname
была добавлена в код. Он работает аналогичноdirname
(корректно с путем/
, путями только с базовым именем, путями с завершающими/
, путями с и без конечных\n
s). Эта функция не может работать корректно, если путь содержит новые строки или некоторые недопустимые символы для текущей локали. Он также заменяет любую комбинацию/
(//
,///
)/
Изменена строка
mkdir "$1" || return 1
наtest -d "$1" || { mkdir "$1" || return 1; }
потому чтоmkdir
завершается с ошибкой, если путь существует, и эта проверка необходима для путей, содержащих конструкции, такие какaaa\.
(Еслиaaa
не существует, предыдущая версия создает,aaa
а затем пытается создать ее снова).Эта версия mkd не генерирует ошибку, если путь уже существует (но у нее все еще есть возможность генерировать такую ошибку при параллельном выполнении) и не может получить несколько каталогов в командной строке.
источник
mkdir -p
, будут слишком старыми (а мы говорим, по крайней мере, пару десятилетий), чтобы иметьprintf
утилиту или поддержку--
для обозначения конца опций.cdirname
бы дали неправильный ответfoo/bar//
, или имена каталогов, содержащие символы новой строки, или недопустимые символы в текущей локали.printf
безопасен в системах POSIX. Поддержка систем POSIXmkdir -p
.mkdir -p
был определен POSIX на протяжении десятилетий.--
начал широко распространяться в системах AT & T, начиная с SysIII, в начале середины 80-х годов.printf
сначала появился какksh
встроенный, я считаю, и был определен POSIX позже, чемmkdir -p
. Некоторые оболочки POSIX (например, основанные на pdksh или yash) по-прежнему не имеютprintf
встроенных функций.Опция
-p
в командеmkdir
делает р ARENT каталогов , как не требуется (нет ошибки , если таковые имеются):Другой способ, например, использовать
&&
(ошибка, если указанная папка существует):Оператор цепочки
&&
используется для объединения команд таким образом, что следующая команда выполняется тогда и только тогда, когда предыдущая команда завершилась без ошибок.Конечно, первый способ лучше.
источник
Это должно сделать это.
источник