Existuje nějaký linuxový příkaz, který přehlížím a který umožňuje dělat něco podle: (pseudo)
$ mkdir -R foo/bar/Zoo/andsoforth
Nebo neexistuje jiná možnost, než vytvořit adresáře jeden po druhém?
$ mkdir -p foo/bar/Zoo/andsoforth
Pomocí mkdir -p
je jednoduchý způsob pro většinu moderních operačních systémů:
mkdir -p foo/bar/Zoo/andsoforth
Nicméně, mkdir -p
se v mnoha příručkách nedoporučuje. Přečtěte si dokumentaci o GNU make
a autoconf
o problémech s používáním mkdir -p
:
Instalační a konfigurační systémy napříč platformami mají své vlastní bezpečné alternativy pro mkdir -p
.
CMake použít v příkazovém řádku Shell:
cmake -E make_directory foo/bar/Zoo/andsoforth
Autoconf pro použití ve skriptu s předběžným zpracováním:
AS_MKDIR_P(foo/bar/Zoo/andsoforth)
nebo:
AC_PROG_MKDIR_P(foo/bar/Zoo/andsoforth)
Tato řešení však vyžadují cmake
nebo autoconf
(M4
) nainstalované nástroje (a možné předzpracování)
Můžete také použít install-sh
skript s -d
možnost:
install-sh -d foo/bar/Zoo/andsoforth
Tento skript je používán v projektech autoconf
a automake
. Myslím, že to musí být nejbezpečnější řešení.
V té době jsem hledal řešení napříč platformami pro standardní /bin/sh
bez závislostí, ale jednu jsme nenašli. Proto jsem napsal další skript, který nemusí být ideální, ale myslím si, že vyhovuje většině požadavků napříč platformami :
#! /bin/sh
cdirname() # cross platform alternative for 'dirname'
{
# $1 - path
test $# -eq 1 || { echo "Procedure 'cdirname' must have only one parameter. Scripting error."; exit 1; }
echo "$1" | sed -n -e '1p' | sed -e 's#//*#/#g' -e 's#\(.\)/$#\1#' -e 's#^[^/]*$#.#' -e 's#\(.\)/[^/]*$#\1#' -
}
mkd() # cross platform alternative for 'mkdir -p'
{
# $1 - directory to create
test $# -eq 1 || { echo "Function 'mkd' can create only one directory (with it's parent directories)."; exit 1; }
test -d "$1" && return 0
test -d "$(cdirname "$1")" || { mkd "$(cdirname "$1")" || return 1; }
test -d "$1" || { mkdir "$1" || return 1; }
return 0
}
Tento skript lze použít pro staré systémy, kde možnost -p
pro mkdir
chybí.
Do kódu byla přidána verze platformy sed
založená na platformě dirname
. Funguje podobným způsobem jako dirname
(opraveno s cestou /
, cesty pouze se základním názvem, cesty s koncem /
, cesty s koncem a bez konců \n
s). Tato funkce nemůže fungovat správně, pokud cesta obsahuje nové řádky nebo neplatné znaky pro aktuální národní prostředí. Nahrazuje také jakoukoli kombinaci /
(//
, ///
) s jedním /
Změněný řádek mkdir "$1" || return 1
to test -d "$1" || { mkdir "$1" || return 1; }
protože mkdir
končí chybou, pokud existuje cesta a tato kontrola je nutná pro cesty obsahující konstrukce jako aaa\.
(Pokud aaa
neexistuje, předchozí verze vytvoří aaa
a poté se ji pokusí znovu vytvořit).
Tato verze mkd negeneruje chybu, pokud již cesta existuje (ale stále má možnost generovat takovou chybu při paralelním provádění) a na příkazovém řádku nemůže získat několik adresářů.
Možnost -p
v příkazu mkdir
vytvoří p arent adresáře podle potřeby (bez chyby, pokud existuje):
mkdir -p foo/bar/Zoo/andsoforth
Jiným způsobem je například použití &&
(chyba, pokud zadaná složka existuje):
mkdir foo && mkdir foo/bar && mkdir foo/bar/Zoo && mkdir foo/bar/Zoo/andsoforth
Operátor řetězení &&
se používá pro zřetězení příkazů dohromady, takže další příkaz se spustí pouze tehdy, pokud předchozí příkaz skončil bez chyb.
První způsob je samozřejmě lepší.