Как использовать mkdir, только если каталог еще не существует?

Я пишу сценарий оболочки для работы под KornShell (ksh) в AIX. Я хотел бы использовать команду mkdir для создания каталога. Но каталог может уже существовать, и в этом случае я не хочу ничего делать. Поэтому я хочу либо проверить, что каталог не существует, либо подавить ошибку «Файл существует», которую mkdir выдает при попытке создать существующий каталог.

Как мне лучше всего это сделать?


person Spike Williams    schedule 27.04.2009    source источник


Ответы (14)


Попробуйте mkdir -p:

mkdir -p foo

Обратите внимание, что это также создаст любые промежуточные каталоги, которые не существуют; например,

mkdir -p foo/bar/baz

создаст каталоги foo, foo/bar и foo/bar/baz, если они не существуют.

Некоторые реализации, такие как GNU mkdir, включают mkdir --parents как более читаемый псевдоним, но он не указан в спецификации POSIX / Single Unix и недоступен на многих распространенных платформах, таких как macOS, различные BSD и различные коммерческие Unix, поэтому его следует избегать.

Если вы хотите получить сообщение об ошибке, когда родительские каталоги не существуют, и хотите создать каталог, если он не существует, вы можете _ 9_ сначала на наличие каталога:

[ -d foo ] || mkdir foo
person Brian Campbell    schedule 27.04.2009
comment
сокращенный пример, который вы используете, - это именно то, чего вам не следует делать. Он меняет логику, чтобы сэкономить место для кода, но его следует использовать! и &&, и будет понятнее для тех, кто ее читает. - person Mike Q; 16.06.2014
comment
В Windows8 кажется, что -p больше не поддерживается, и это поведение по умолчанию. - person angularsen; 09.10.2014
comment
@AndreasLarsen Этот вопрос касается mkdir в Unix-подобных системах, а не в Windows. -p требуется для соответствия спецификации POSIX / Single Unix, поэтому все, что намеревается соответствовать этим спецификациям, будет поддерживать -p. Windows совершенно другая, если вы не используете уровень эмуляции POSIX, такой как Cygwin или MSYS. - person Brian Campbell; 09.10.2014
comment
Я обнаружил сегодня кое-что интересное с mkdir -p, вы можете использовать скобки! {} для создания сложного дерева каталогов в команде. См. Здесь: technosophos.com/2010/04 / 15 / - person herve; 04.02.2016
comment
@MikeQ Я бы предпочел || вместо &&, потому что тогда вся строка будет иметь правильный статус выхода. Важно, если ваша оболочка работает с errexit или если эта строка является последней в функции, case-case, что угодно. - person rudimeier; 13.03.2016
comment
@herve Это не имеет ничего общего с mkdir; оболочка расширяет такое выражение до дискретного списка аргументов, которые передаются в mkdir. - person chepner; 31.10.2017
comment
Вы определенно правы. Тем не менее, в этом случае он действительно мощный. - person herve; 01.11.2017
comment
@herve Спасибо за это! Точно не знал об этом и пригодится в будущем! - person Victor Ude; 20.07.2018
comment
Работает ли это с подстановочным знаком перед промежуточными шагами? Ex / * / foo / bar / baz? - person akozi; 17.09.2018
comment
@akozi Да, если соответствующие каталоги уже существуют на уровне, на котором используется подстановочный знак. В оболочке расширение glob происходит перед передачей аргументов программе (в данном случае mkdir). Итак, если у вас есть каталоги a, b и c, mkdir -p */foo/bar/baz будет таким же, как mkdir -p a/foo/bar/baz b/foo/bar/baz c/foo/bar/baz. mkdir может принимать несколько аргументов, и когда задано -p, он создаст необходимые промежуточные каталоги. Поэкспериментируйте с этим сами. Попробуйте echo mkdir -p */foo/bar/baz увидеть, какая команда запущена; или просто попробуйте запустить его в тестовом каталоге. - person Brian Campbell; 24.01.2019
comment
@herve discovery очень кстати. Пожалуйста, не забывайте не оставлять пробелов ни в одной части этого скрипта. - person RicarHincapie; 18.08.2020

Это должно работать:

$ mkdir -p dir

or:

if [[ ! -e $dir ]]; then
    mkdir $dir
elif [[ ! -d $dir ]]; then
    echo "$dir already exists but is not a directory" 1>&2
fi

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

person Alnitak    schedule 27.04.2009
comment
Я не думаю, что в korn есть оператор -d, скорее -e используется для обоих файлов / каталогов и просто проверяет наличие. Кроме того, все они возвращают 0 в случае успеха, так что! является избыточным. Поправьте меня если я ошибаюсь. - person alkar; 27.04.2009
comment
неправильно по обоим пунктам, AFAIK. тесты возвращают true в случае успеха, и -d тоже существует (по крайней мере, на MacOS X) - person Alnitak; 27.04.2009
comment
возможно, стоит упомянуть, что это не совсем потокобезопасно. Между временем, когда вы проверяете, существует ли каталог, и временем, когда вы пытаетесь писать, все может измениться. - person Justin L.; 12.03.2015

Используйте флаг -p.

man mkdir
mkdir -p foo
person jimmyorr    schedule 27.04.2009
comment
-p, --parents нет ошибки, если существует, создать родительские каталоги по мере необходимости - person Swagger 68; 02.05.2021

Определение сложных деревьев каталогов с помощью одной команды

mkdir -p project/{lib/ext,bin,src,doc/{html,info,pdf},demo/stat/a}
person Oleg    schedule 21.08.2013
comment
нет ошибки, если существует, создайте родительские каталоги по мере необходимости - person Fedir RYKHTIK; 07.04.2016
comment
Имейте в виду, что это свойство не самого mkdir, а оболочки, которая выполняет команду. Это называется расширением скобок - AFAIK, его поддерживают только Bash, ksh, zsh и оболочка C. - person Daniel Kamil Kozar; 24.05.2016
comment
если у вас есть пробелы вокруг запятых, вы можете (получите) неожиданный результат. Остерегаться. - person Atlas7; 30.06.2017
comment
@ Atlas7 заявил, что вам нужно будет экранировать символы, которые обычно являются частью регулярного выражения. (т.е. вместо использования folder name вам нужно использовать folder\ name) - person John Hamilton; 19.01.2018
comment
Это не ответ; это отдельная тема, более уместная в качестве комментария. - person Chris Page; 03.11.2019
comment
Определение? Вы имеете в виду создание? - person Peter Mortensen; 12.06.2020

Если вы не хотите показывать сообщение об ошибке:

[ -d newdir ] || mkdir newdir

Если вы хотите показать собственное сообщение об ошибке:

[ -d newdir ] && echo "Directory Exists" || mkdir newdir
person Jahid    schedule 27.03.2015

Старый проверенный и верный

mkdir /tmp/qq >/dev/null 2>&1

будет делать то, что вы хотите, без каких-либо условий гонки, которые есть у многих других решений.

Иногда самые простые (и самые уродливые) решения оказываются лучшими.

person Community    schedule 27.04.2009
comment
Это не удастся, если tmp не существует. и это не дает вам никакого подтверждения. - person Mike Q; 16.06.2014
comment
Условия гонки? Можете ли вы уточнить свой ответ? Неатомарное тестирование и создание? - person Peter Mortensen; 12.06.2020
comment
@Peter, фрагмент, подобный (например) [ -d newdir ] || mkdir newdir, где каталог изначально не существует, имеет состояние гонки, в котором между проверкой существования и попыткой создания другой процесс может налететь и создать каталог. Следовательно, mkdir тогда потерпит неудачу. - person paxdiablo; 13.06.2020
comment
@Mike Q: базовый путь /tmp, вероятно, был выбран в примере для представления базового пути, который всегда существует и имеет возможность записи для текущего пользователя, например у пользователя достаточно прав для создания каталога. Вы поднимаете правильную мысль: логика немного противоречива, поскольку, когда эта команда не работает, это может означать две вещи: 1.) каталог существует или 2.) каталог не удалось создать. Это неверно для самой операции, поэтому простая пост-проверка пути к каталогу может дать подтверждение или следующую команду, которая работает. - person hakre; 25.06.2021

mkdir foo работает, даже если каталог существует. Чтобы он работал, только если каталог с именем «foo» не существует, попробуйте использовать флаг -p.

Пример:

mkdir -p foo

Это создаст каталог с именем «foo», только если он не существует. :)

person Atul Ranjan    schedule 20.01.2014
comment
Как упоминалось @BrianCampbell, это также создаст любые другие каталоги на пути. Это может быть опасно, если, например, том становится размонтированным, так как он может создавать каталоги в точке монтирования. - person uliwitness; 22.04.2015

mkdir больше не поддерживает переключатель -p в системах Windows 8+.

Вы можете использовать это:

IF NOT EXIST dir_name MKDIR dir_name
person Karanvir Kang    schedule 22.11.2016
comment
OP был про корншелл AIX ... не имеет отношения к Windows, не так ли? - person J. Chomel; 27.04.2017
comment
Вы уверены, что он поддерживался раньше? У вас есть источник? - person Peter Mortensen; 12.06.2020

Вы можете использовать оператор if, чтобы проверить, существует ли каталог. Если не выходит, создайте каталог.

  1. dir = / home / dir_name

    if [ ! -d $dir ]
    then
         mkdir $dir
    else
         echo "Directory exists"
    fi
    
  2. Вы можете использовать каталог mkdir с параметром -p для создания каталога. Он проверит, недоступен ли каталог.

    mkdir -p $dir
    

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

    mkdir -p /home/parent_dir /home/parent_dir/child1 /home/parent_dir/child2
    
person AbhinavVaidya8    schedule 21.08.2018
comment
Есть ли преимущество в использовании цикла if !? зачем кому-то выбирать эту опцию -p ?! - person pedram bashiri; 29.08.2018
comment
Я поделился с вами способами создания папок, когда папка не существует. Это зависит от требований к одному. Если у вас есть случай использования, когда вам нужно проверить, не существует ли папка, и вы хотите отслеживать это, чтобы вы могли использовать решение 1. Если это не имеет значения, вы можете использовать решение 2, оно создаст папку если не существует. - person AbhinavVaidya8; 02.09.2018
comment
Я не видел петли. - person Amit Naidu; 20.06.2019

Ссылаясь на страницу руководства man mkdir для опции -p

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

который создаст все каталоги по заданному пути, если существует, не выдает ошибок, в противном случае он создает все каталоги слева направо по заданному пути. Попробуйте следующую команду. каталоги newdir и anotherdir не существуют до выполнения этой команды

Правильное использование

mkdir -p /tmp/newdir/anotherdir

После выполнения команды вы увидите, что newdir и anotherdir созданы в / tmp. Вы можете вводить эту команду сколько угодно раз, команда всегда имеет exit(0). По этой причине большинство людей используют эту команду в сценариях оболочки перед тем, как использовать эти фактические пути.

person vkrams    schedule 21.01.2019

Или, если вы хотите сначала проверить наличие:

if [[ ! -e /path/to/newdir ]]; then
            mkdir /path/to/newdir
fi

-e - это тест на существование для KornShell.

Вы также можете попробовать поискать в Google руководство по KornShell.

person alkar    schedule 27.04.2009

Это простая функция (оболочка Bash), которая позволяет вам создать каталог, если он не существует.

#------------------------------------------#
# Create a directory if it does not exist. #
#------------------------------------------#
# Note the "-p" option in the mkdir        #
# command which creates directories        #
# recursively.                             #
#------------------------------------------#
createDirectory() {
   mkdir -p -- "$1"
}

Вы можете вызвать указанную выше функцию как:

createDirectory $ (mktemp -d dir-example.XXXXX) / fooDir / BarDir

Вышеупомянутое создает fooDir и BarDir, если они не существуют. Обратите внимание на параметр -p в команде mkdir, которая рекурсивно создает каталоги.

person Balaji Boggaram Ramanarayan    schedule 14.02.2018

mkdir -p sam
  • mkdir = Создать каталог
  • -p = --parents
  • (нет ошибки, если существует, создайте родительские каталоги по мере необходимости)
person Paritosh Yadav    schedule 20.04.2018

Просто, бесшумно и смертельно опасно:

mkdir -p /my/new/dir >/dev/null 2>$1
person moodboom    schedule 15.12.2020
comment
Нет любви..................? - person moodboom; 02.06.2021