Как 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
возможно, стоит упомянуть, что это не совсем потокобезопасно. между временем, когда вы проверяете, существует ли каталог, и временем, когда вы пытаетесь написать, все может измениться.
Джастин Л.
89

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

man mkdir
mkdir -p foo
jimmyorr
источник
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
Jahid
источник
20

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

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

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

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

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

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

Пример :-

mkdir -p foo

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

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

if [ -d $directory_name ]
then
    echo "Directory already exists"
else
    mkdir $directory_name
fi
Вишува Бхарати К
источник
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). По этой причине большинство людей используют эту команду в сценариях оболочки, прежде чем использовать эти фактические пути.

vkrams
источник
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
AbhinavVaidya8
источник
Есть ли преимущество в использовании цикла 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
Алекс Зубков
источник