Почему в mkdir по умолчанию не установлен флаг -p, позволяющий создавать вложенные каталоги?

11

Я не вижу причин, по которым -pфлаг mkdirне должен быть установлен по умолчанию.

  -p, --parents     no error if existing, make parent directories as needed

Из того, что я вижу, это неразрушающая команда. Я пропустил что-то важное о том, как это работает?

Во-вторых, есть ли простой способ установить поведение по умолчанию mkdir?

Treffynnon
источник
2
это в вашем .bashrc: alias mkdir="mkdir -p".
Кевин
После всего обсуждения я решил пойти с псевдонимомmkdp
Треффиннон

Ответы:

6

Это необязательная функция, которая не всегда желательна, особенно в сценариях. Рассмотрим следующие недостатки в случае сценариев:

  • О том, что каталог уже существует, не сообщается: если сценарий должен поместить некоторые файлы во вновь созданный каталог, и этот каталог уже существует и содержит файлы, сценарий может создать много беспорядка. (Позже будет сложно отфильтровать файлы, которые были помещены туда сценарием.)
  • С другой стороны, некоторые сценарии (или их части) могут зависеть от структуры каталогов, созданной ранее (возможно, другим пакетом / сценарием). Например, сценарию установки пакета может потребоваться поместить библиотеки в подкаталог /usr/local/lib/GreatSoftware/ImportantPartOfIt, но библиотеки зависят от / link, находящейся в каталоге /usr/local/lib/GreatSoftware. Если это отсутствует, сценарий не должен продолжаться.

Общее поведение mkdirделает его простым и естественным, так как о таких ситуациях сообщают, и их можно поймать сразу.


Вы можете сделать для него псевдоним, если хотите всегда использовать mkdir -pв своих оболочках:

alias mkdir='mkdir -p'

(Это должно быть в вашей .bashrcили любой другой конфигурации вашей оболочки.)

rozcietrzewiacz
источник
1
Я бы не предложил псевдоним стандартной команды, чтобы она велась нестандартным образом. Это сделало бы сценарии не переносимыми и могло бы запутать читателей. Создание нового псевдонима или функции, как alias mkdp="mkdir -p"было бы более целесообразно.
Jlliagre
2
@jlliagre Нет, это не повлияет на сценарии. Псевдонимы, определенные локально в .bashrc(обычно), не влияют на их среду.
rozcietrzewiacz
Действительно, но ты упустил мою точку зрения. Использование псевдонимов стандартной команды для изменения ее поведения даже для собственного использования не рекомендуется. Худший пример - вездесущий alias rm='rm -i'.
Jlliagre
1
@jlliagre Не рекомендуется кем? ;) Но да, я согласен, я бы сам использовал другой псевдоним - но по практическим, а не идеологическим причинам. Я также не думаю, что rm -iпсевдоним всегда плох, хотя может привести к вредным привычкам. Конечно, не все псевдонимы команд одинаково хороши / плохи - рассмотрим ls="ls --color=auto"или ssh="TERM=xterm ssh"например.
rozcietrzewiacz
В моей рекомендации нет ничего идеологического. Псевдоним rm косвенно отвечает за многие потерянные файлы (я встречал множество жертв этого псевдонима). Я подозревал, что у mkdir гораздо меньше нежелательных побочных эффектов. Конечно, я не против косметических, не поведенческих изменений, подобных вашим ssh и ls.
Jlliagre
16

Конечно, можно утверждать, что создание родительского каталога должно быть по умолчанию, и можно использовать некоторую опцию проверки, чтобы предотвратить создание каталога, если родительский объект не существует.

Но причина, по которой все наоборот, - просто история. Базовая версия mkdir не создавала родительские каталоги. Вот почему в дистрибутивах X11 появилась команда с именем mkdirhier, которая смогла выполнить эту задачу: проверить, существуют ли родительские каталоги, и при необходимости создать их.

Позже эта функциональность была добавлена ​​к команде mkdir во многих версиях UNIX (я не знаю, входит ли она в стандарт POSIX в настоящее время). Для поддержания совместимости эта функция была доступна при включении флага опции: -p.

Почему плохо включить его по умолчанию? Сценарии могут полагаться на сбой mkdir, если родительский каталог не существует. Тем более, что пользователь root может по умолчанию создавать деревья каталогов.

Пример:

 if mkdir /backup/$(uname -n)/$(date +%Y%m%d)
  then
    perform_backup ...

В этом примере каталог будет создан, и резервное копирование будет выполнено даже в том случае, если файловая система /backupне смонтирована, а родительский /backup/$(uname -n)объект не существует, если по умолчанию будет наоборот.

Практическое правило. Рекомендуется не изменять поведение по умолчанию для любого инструмента. При желании укажите параметры, позволяющие изменить поведение по умолчанию.

КТФ
источник
2
Мне нравится пример горы, который вы использовали здесь. Я не думал об этом конкретном сценарии.
Треффиннон
1
Опции -p (и -m) были введены System V в 1983 году. Обе они определенно являются частью стандарта POSIX.
Jlliagre
4

Я думаю, это своего рода философия. Голая команда mkdir (1) (без опций) представляет системный вызов mkdir (2) , обеспечивающий его функциональность в оболочке и не делающий ничего более или менее.

ern0
источник
4

В начале была только голая mkdirкоманда. В соответствии с принципами проектирования Unix, эта простая команда выполняла одну простую задачу: создание каталога.

Позже, mkdirприобрел -pопцию для обработки общего случая использования, когда вызывающая сторона хочет создать ноль, один или несколько каталогов, чтобы гарантировать, что конкретный путь существует. Это не было сделано операцией по умолчанию по нескольким причинам. Во-первых, не во всех системах была эта более сложная функция, и -pналичие опции означало, что сценарии, которые ее использовали, получали бы разумное сообщение об ошибке (что-то вроде этого mkdir: invalid option -z), а не странно не могли иногда создавать каталоги. Во-вторых, и самое главное, поведение mkdir -pне является совместимой заменой mkdirво всех случаях.

В частности, на большинстве файловых систем mkdirэто атомарная операция . Если программа выполняется mkdir playgroundи команда выполнена успешно, она знает, что создала playgroundкаталог. Это позволяет программе рассматривать новый каталог как свою исключительную игровую площадку: если другой экземпляр той же программы работает одновременно, ее вызов mkdir playgroundзавершится неудачно. Это свойство явно не предоставляется, mkdir -pтак как оно позволяет аргументу существовать.

Если бы mkdir -pон существовал с самого начала, его можно было бы сделать режимом по умолчанию, например, mkdir -aдля команды создания одного каталога. Но это не следовало бы обычной философии проектирования Unix: большинство базовых утилит представляют собой простые обертки вокруг базовых примитивов, причём более причудливое поведение (например, создание нескольких каталогов за один раз) требует необычных опций.

Жиль "ТАК - прекрати быть злым"
источник
2

Для меня проблема в том, что поведение параметра -p, если оно было значением по умолчанию, по сути является побочным эффектом. Это добавляет сложности команде, делая что-то дополнительное к тому, что вы просили сделать. Это еще одна невидимая вещь, которую нужно помнить. Одно из основных правил практики здорового программирования - избегать побочных эффектов.

Современные языки программирования настолько мощны, что относительно легко собрать любую сложную команду, которая может вам понадобиться, из примитивов, которые предоставляет язык. Это включает в себя принятие сознательного решения о том, какое поведение требуется, а также оставляет конкретную, видимую запись того, что было сделано.

Джо
источник