Использование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
}
Этот скрипт можно использовать для старых систем, где опция -p
for mkdir
отсутствует.
sed
кросс-платформенная версия dirname
была добавлена в код. Он работает аналогично dirname
(корректно с путем /
, путями только с базовым именем, путями с завершающими /
, путями с и без конечных \n
s). Эта функция не может работать корректно, если путь содержит новые строки или некоторые недопустимые символы для текущей локали. Он также заменяет любую комбинацию /
( //
, ///
)/
Изменена строка mkdir "$1" || return 1
на test -d "$1" || { mkdir "$1" || return 1; }
потому что mkdir
завершается с ошибкой, если путь существует, и эта проверка необходима для путей, содержащих конструкции, такие как aaa\.
(Если aaa
не существует, предыдущая версия создает, aaa
а затем пытается создать ее снова).
Эта версия mkd не генерирует ошибку, если путь уже существует (но у нее все еще есть возможность генерировать такую ошибку при параллельном выполнении) и не может получить несколько каталогов в командной строке.