Как mkdir только если dir еще не существует?


1989

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

Есть мысли о том, как лучше это сделать?

Ответы:


3296

Попробуй 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, поэтому этого следует избегать.

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

[ -d foo ] || mkdir foo

11
сокращенный пример, который вы используете, это именно то, что вы не должны делать. Это изменяет логику, чтобы сэкономить место для кодирования, но оно должно использовать! и && и больше смысла читающим.
Майк К

16
@AndreasLarsen Этот вопрос касается mkdirUnix-подобных систем, а не Windows. -pтребуется для соответствия спецификации POSIX / Single Unix, поэтому все, что намеревается соответствовать этим спецификациям, будет поддерживать -p. Windows совершенно другая, если только вы не используете слой эмуляции POSIX, такой как Cygwin или MSYS.
Брайан Кэмпбелл

23
Сегодня я обнаружил кое-что интересное mkdir -p, вы можете использовать скобки! {}создать «сложное» дерево каталогов в команде. Смотрите здесь: technosophos.com/2010/04/15/...
Эрве

12
@MikeQ Я бы предпочел ||вместо, &&потому что тогда вся строка имеет правильный статус выхода. Важно, если ваша оболочка работает с errexitили эта строка является последней в функции, switch-case, что угодно.
rudimeier

9
@herve Это не имеет ничего общего с mkdir; оболочка расширяет такое выражение до дискретного списка аргументов, которые передаются mkdir.
Чепнер

177

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

$ mkdir -p dir

или:

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

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


Я не думаю, что в korn есть оператор -d, скорее, он используется для обоих файлов / каталогов и просто проверяет существование. Кроме того, все они возвращают 0 в случае успеха, так что! избыточно Поправьте меня если я ошибаюсь.
Алькар

1
неправильно по обоим пунктам, AFAIK. в случае успеха тесты возвращают значение true , и -d тоже существует (по крайней мере, в MacOS X)
Alnitak,

5
возможно, стоит упомянуть, что это не совсем потокобезопасно. между временем, когда вы проверяете, существует ли каталог, и временем, когда вы пытаетесь написать, все может измениться.
Джастин Л.


74

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

mkdir -p project/{lib/ext,bin,src,doc/{html,info,pdf},demo/stat/a}

без ошибок, если есть, создайте родительские каталоги по необходимости
Fedir RYKHTIK

19
Имейте в виду, что это не особенность mkdir, а оболочка, которая выполняет команду. Это называется расширением скобок - AFAIK, только Bash, ksh, zsh и оболочка C поддерживают его.
Даниэль Камил Козар

3
если у вас есть пробелы вокруг запятых, вы можете (получите) неожиданный результат. Осторожно.
Atlas7

1
@ Atlas7 заявил, что вам нужно экранировать символы, которые обычно являются частью регулярного выражения. (т.е. вместо того, чтобы использовать, folder nameвам нужно использовать folder\ name)
Джон Гамильтон

1
Это не ответ; это отдельная тема, которая была бы более уместной в качестве комментария.
Крис Пейдж

40

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

[ -d newdir ] || mkdir newdir

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

[ -d newdir ] && echo "Directory Exists" || mkdir newdir

20

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

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

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

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


5
Это потерпит неудачу, если «tmp» не существует. и при этом это не дает Вам никакого подтверждения.
Майк К

15

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

Пример :-

mkdir -p foo

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


2
Как упомянуто @BrianCampbell, это также создаст любые другие каталоги в пути. Это может быть опасно, если, например, том отключается, поскольку он может создавать каталоги в точке монтирования.
Uliwitness


10

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

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

-e это существующий тест для оболочки korn.

Вы также можете попробовать поискать руководство по оболочке korn.


10

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

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

IF NOT EXIST dir_name MKDIR dir_name

10
ОП был про AIX kornshell ... не имеет ничего общего с Windows, не так ли?
J.

9

Ссылаясь на справочную страницу 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). По этой причине большинство людей используют эту команду в сценариях оболочки, прежде чем использовать эти фактические пути.


8

Вы можете использовать цикл 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

Есть ли преимущество в использовании цикла if !? почему кто-то выбрал бы этот вариант -p ?!
Педрам Башири

1
Я поделился с вами способами создания папок, когда папка не существует. Это зависит от требования к одному. Если у вас есть сценарий использования, в котором вам нужно проверить, не существует ли папка, и вы хотите отследить ее, чтобы перейти к решению 1. Если это не имеет значения, вы можете перейти к решению 2, оно создаст папку если не существует
AbhinavVaidya8

Я не видел петли.
Амит Найду

3

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

#----------------------------------
# Create a directory if it doesn't exist
#------------------------------------
createDirectory() {
    if [ ! -d $1 ]
        then
        mkdir -p $1
    fi
}

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

createDirectory / tmp / fooDir / BarDir

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


2
mkdir -p sam
  • mkdir = Создать каталог
  • -p = --parents
  • (без ошибок, если есть, создайте родительские каталоги по мере необходимости)

2
if [ !-d $dirName ];then
     if ! mkdir $dirName; then  # Shorter version. Shell will complain if you put braces here though
     echo "Can't make dir: $dirName"
     fi
fi
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.