рекурсивний mkdir


305

Чи є команда linux, яку я оглядаю, яка дозволяє щось робити за рядками: (псевдо)

$ mkdir -R foo/bar/zoo/andsoforth

Або немає альтернативи, крім того, щоб робити каталоги по одному?



1
смішно, я дивився на цю сторінку, але зовсім не помічав "батьків", тому що думав про них як про дітей (зліва направо).

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

1
Особисто я не помітив "батьків" на сторінці "man", тому що, мабуть, я відчуваю, що прапор повинен бути "-r" для "рекурсивного" - або, принаймні, має бути псевдонім для таких, оскільки mkdirмає лише 6 загалом задокументовані прапори. Чорт, я відчуваю, що команда повинна створювати каталоги за замовчуванням рекурсивно, і якщо ви цього не хочете, вам слід вказати так чітко.
jbowman

Відповіді:


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

92
FYI the -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
}

Цей скрипт можна використовувати для старих систем, де параметр -pдля mkdirвідсутній.

seddirnameдо коду була додана версія міжплатформованої крос-платформи . Він працює з аналогічним способом dirname(правильний з контуром /, контури лише з базовою назвою, контури з трейлінгами /, контури з трейлінгами та без них \n). Ця функція не може працювати правильно, якщо у шляху є нові рядки або деякі недійсні символи для поточного локалу. Він також замінює будь-яку комбінацію /( //, ///) з одинарною/

Змінено рядок mkdir "$1" || return 1на test -d "$1" || { mkdir "$1" || return 1; }тому, що mkdirзакінчується помилкою, якщо існує шлях, і ця перевірка потрібна для шляхів, що містять конструкції типу aaa\.(Якщо aaaне існує попередньої версії, aaaа потім намагається створити її знову).

Ця версія mkd не генерує помилку, якщо шлях вже існує (але він все ще має можливість генерувати таку помилку при паралельному виконанні) і не може отримати декілька каталогів у командному рядку.


4
"mkdir -p" визначається позисом. Які варіанти Unix або Unix не підтримують його? (І це не повинно бути оболонкою вбудованої, хоча я припускаю , що це не якась - або причина не може бути.) Pubs.opengroup.org/onlinepubs/9699919799/utilities/mkdir.html
Tim B

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робить необхідні каталоги p 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.