Використання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
для mkdir
відсутній.
sed
dirname
до коду була додана версія міжплатформованої крос-платформи . Він працює з аналогічним способом dirname
(правильний з контуром /
, контури лише з базовою назвою, контури з трейлінгами /
, контури з трейлінгами та без них \n
). Ця функція не може працювати правильно, якщо у шляху є нові рядки або деякі недійсні символи для поточного локалу. Він також замінює будь-яку комбінацію /
( //
, ///
) з одинарною/
Змінено рядок mkdir "$1" || return 1
на test -d "$1" || { mkdir "$1" || return 1; }
тому, що mkdir
закінчується помилкою, якщо існує шлях, і ця перевірка потрібна для шляхів, що містять конструкції типу aaa\.
(Якщо aaa
не існує попередньої версії, aaa
а потім намагається створити її знову).
Ця версія mkd не генерує помилку, якщо шлях вже існує (але він все ще має можливість генерувати таку помилку при паралельному виконанні) і не може отримати декілька каталогів у командному рядку.