Использование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 не генерирует ошибку, если путь уже существует (но у нее все еще есть возможность генерировать такую ошибку при параллельном выполнении) и не может получить несколько каталогов в командной строке.