Jak mkdir tylko wtedy, gdy katalog jeszcze nie istnieje?


1987

Piszę skrypt powłoki, aby działał pod KornShell (ksh) w systemie AIX. Chciałbym użyć mkdirpolecenia, aby utworzyć katalog. Ale katalog może już istnieć, w którym to przypadku nie chcę nic robić. Dlatego chcę albo przetestować, aby stwierdzić, że katalog nie istnieje, albo ukryć błąd „Plik istnieje”, który mkdirpojawia się, gdy próbuje utworzyć istniejący katalog.

Wszelkie przemyślenia na temat tego, jak najlepiej to zrobić?

Odpowiedzi:


3293

Spróbuj mkdir -p:

mkdir -p foo

Zauważ, że spowoduje to również utworzenie nieistniejących katalogów pośrednich; na przykład,

mkdir -p foo/bar/baz

utworzy katalogi foo, foo/bara foo/bar/bazjeśli nie istnieją.

Niektóre implementacje, takie jak GNU, mkdirzawierają mkdir --parentsbardziej czytelny alias, ale nie jest to określone w specyfikacji POSIX / Single Unix i nie jest dostępne na wielu popularnych platformach, takich jak macOS, różne BSD i różne komercyjne Uniksy, więc należy tego unikać.

Jeśli chcesz błąd, gdy katalogi nadrzędne nie istnieją i chcesz utworzyć katalog, jeśli nie istnieje, możesz najpierw utworzyć testkatalog:

[ -d foo ] || mkdir foo

11
skrócony przykład, którego używasz, jest dokładnie tym, czego nie powinieneś robić. Odwraca logikę, aby zaoszczędzić miejsce na kodowanie, ale należy jej użyć! oraz && i mają większy sens dla osób czytających.
Mike Q

16
@AndreasLarsen To pytanie dotyczy mkdirsystemów uniksopodobnych, a nie Windows. -pjest wymagany do zgodności ze specyfikacją POSIX / Single Unix Specification, więc wszystko, co będzie zgodne z tymi specyfikacjami, będzie obsługiwane -p. Windows jest zupełnie inny, chyba że użyjesz warstwy emulacji POSIX, takiej jak Cygwin lub MSYS.
Brian Campbell

22
Odkryłem dziś coś ciekawego mkdir -p, możesz użyć nawiasów! {}aby utworzyć „złożone” drzewo katalogów w poleceniu. Zobacz tutaj: technosophos.com/2010/04/15/…
herve

12
@MikeQ Wolałbym ||zamiast, &&ponieważ wtedy cała linia ma właściwy status wyjścia. Ważne, jeśli twoja powłoka działa z errexitlub jeśli ta linia jest ostatnią linią w funkcji, przełączniku, cokolwiek.
rudimeier

9
@herve To nie ma nic wspólnego mkdir; powłoka rozwija takie wyrażenie na dyskretną listę argumentów, które są przekazywane mkdir.
chepner

176

To powinno działać:

$ mkdir -p dir

lub:

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

który utworzy katalog, jeśli nie istnieje, ale ostrzega, jeśli nazwa katalogu, który próbujesz utworzyć, jest już używana przez coś innego niż katalog.


Nie sądzę, żeby w kornie był operator -d, raczej -e jest używane zarówno do plików / katalogów, jak i do sprawdzania istnienia. Ponadto wszystkie zwracają 0 po sukcesie, więc! jest zbędny. Popraw mnie, jeśli się mylę.
alkar

1
źle w obu przypadkach, AFAIK. testy zwracają prawdę po sukcesie, a -d też istnieje (przynajmniej na MacOS X)
Alnitak

5
warto wspomnieć, że nie jest to całkowicie bezpieczne dla wątków. między czasem sprawdzania, czy katalog istnieje, a czasem, gdy próbujesz pisać, wszystko może się zmienić.
Justin L.


73

Definiowanie złożonych drzew katalogów za pomocą jednego polecenia

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

bez błędu, jeśli istnieje, w razie potrzeby utwórz katalogi nadrzędne
Fedir RYKHTIK,

18
Pamiętaj, że nie jest to cecha mkdirsama w sobie, ale powłoka, która wykonuje polecenie. Nazywa się to rozszerzaniem nawiasów klamrowych - AFAIK, obsługują go tylko Bash, ksh, zsh i powłoka C.
Daniel Kamil Kozar

3
jeśli masz spacje wokół przecinków, możesz (nie) uzyskać nieoczekiwanego wyniku. Strzec się.
Atlas7

1
@ Atlas7 stwierdził, że musisz uciec od znaków, które zwykle są częścią wyrażenia regularnego. (tzn. zamiast używać folder namemusisz użyć folder\ name)
John Hamilton

1
To nie jest odpowiedź; jest to osobny temat, który byłby bardziej odpowiedni jako komentarz.
Chris Page

40

Jeśli nie chcesz wyświetlać żadnego komunikatu o błędzie:

[ -d newdir ] || mkdir newdir

Jeśli chcesz wyświetlić własny komunikat o błędzie:

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

20

Stare wypróbowane i prawdziwe

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

zrobi to, co chcesz, w żadnym z warunków wyścigu, które ma wiele innych rozwiązań.

Czasem najprostsze (i najbrzydsze) rozwiązania są najlepsze.


5
To się nie powiedzie, jeśli „tmp” nie istniał. nie daje też żadnego potwierdzenia.
Mike Q

15

mkdir foodziała, nawet jeśli katalog istnieje. Aby działał tylko wtedy, gdy katalog o nazwie „foo” nie istnieje, spróbuj użyć -pflagi.

Przykład: -

mkdir -p foo

Spowoduje to utworzenie katalogu o nazwie „foo”, tylko jeśli nie istnieje. :)


2
Jak wspomniano @BrianCampbell, spowoduje to również utworzenie innych katalogów na ścieżce. Może to być niebezpieczne, jeśli np. Wolumin zostanie odmontowany, ponieważ może tworzyć katalogi w punkcie montowania.
uliwitness

11
directory_name = "foo"

if [ -d $directory_name ]
then
    echo "Directory already exists"
else
    mkdir $directory_name
fi

10

Lub jeśli chcesz najpierw sprawdzić istnienie:

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

-e to istniejący test dla powłoki Korn.

Możesz także wypróbować przeglądanie instrukcji obsługi skorupy Korn.


10

mkdir nie obsługuje już przełączania -p w systemach Windows 8+.

Możesz użyć tego:

IF NOT EXIST dir_name MKDIR dir_name

10
OP dotyczyło kornshell AIX ... nie ma nic wspólnego z Windows, prawda?
J. Chomel

9

Odwoływanie się do strony man mkdirpodręcznika dla opcji -p

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

który utworzy wszystkie katalogi na danej ścieżce, jeśli istnieje, nie spowoduje błędu, w przeciwnym razie utworzy wszystkie katalogi od lewej do prawej na danej ścieżce. Wypróbuj poniższe polecenie. katalogi newdiri anotherdirnie istnieje przed wydaniem tego polecenia

Prawidłowa obsługa

mkdir -p /tmp/newdir/anotherdir

Po wykonaniu polecenia możesz zobaczyć newdiri anotherdirutworzyć w / tmp. Możesz wydać to polecenie tyle razy, ile chcesz, polecenie zawsze ma exit(0). Z tego powodu większość ludzi używa tego polecenia w skryptach powłoki przed użyciem rzeczywistych ścieżek.


8

Możesz użyć pętli if, aby sprawdzić, czy katalog istnieje, czy nie, jeśli nie wychodzi, niż utworzyć katalog.

1) dir = / home / dir_name

if [ ! -d $dir ]
then
     mkdir $dir
else
     echo "Directory exists"  
fi

2) Możesz stworzyć katalog używając mkdir z opcją -p. Sprawdza, czy katalog nie jest dostępny, będzie.

mkdir -p $dir

mkdir -p pozwala również utworzyć strukturę drzewa katalogu. Jeśli chcesz utworzyć katalog macierzysty i podrzędny za pomocą tego samego polecenia, możesz wybrać mkdir -p

mkdir -p /home/parent_dir /home/parent_dir/child1 /home/parent_dir/child2

Czy jest jakaś korzyść z używania pętli if !? dlaczego ktoś miałby wybrać tę opcję over -p ?!
pedram bashiri

1
Udostępniłem ci sposoby tworzenia folderów, gdy folder nie istnieje. To zależy od jednego wymagania. Jeśli masz przypadek użycia, w którym musisz sprawdzić, czy folder nie istnieje, i chcesz to śledzić, aby przejść do rozwiązania 1. Jeśli nie ma to znaczenia, możesz przejść do rozwiązania 2, spowoduje to utworzenie folderu jeśli nie istnieje.
AbhinavVaidya8

Nie widziałem pętli.
Amit Naidu

3

Jest to prosta funkcja (powłoka bash), która pozwala utworzyć katalog, jeśli nie istnieje.

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

Możesz wywołać powyższą funkcję jako:

createDirectory / tmp / fooDir / BarDir

Powyższe tworzy fooDir i BarDir, jeśli nie istnieją. Zwróć uwagę na opcję „-p” w komendzie mkdir, która rekursywnie tworzy katalogi. Mam nadzieję że to pomoże.


2
mkdir -p sam
  • mkdir = Utwórz katalog
  • -p = - rodzice
  • (jeśli nie ma błędu, w razie potrzeby utwórz katalogi nadrzędne)

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.