$ mkdir -p foo/bar/zoo/andsoforth
Existe um comando do Linux que estou negligenciando que torna possível fazer algo nos moldes de: (pseudo)
$ mkdir -R foo/bar/zoo/andsoforth
Ou não há outra alternativa senão fazer os diretórios um de cada vez?
O uso de mkdir -p
é uma maneira mais simples para a maioria dos oses modernos:
mkdir -p foo/bar/zoo/andsoforth
No entanto, o uso de mkdir -p
não é recomendado em muitos manuais. Leia a documentação para as versões mais recentes do gnu make
e autoconf
sobre problemas com o uso de mkdir -p
:
Os sistemas de instalação e configuração entre plataformas têm suas próprias alternativas seguras para mkdir -p
.
CMake para usar na linha de comando do shell:
cmake -E make_directory foo/bar/zoo/andsoforth
Autoconf para usar no script com pré-processamento:
AS_MKDIR_P(foo/bar/zoo/andsoforth)
ou:
AC_PROG_MKDIR_P(foo/bar/zoo/andsoforth)
Mas essas soluções exigem que as ferramentas cmake
ou autoconf
( M4
) sejam instaladas (e possível pré-processamento)
Você também pode usar o script install-sh
com a opção -d
:
install-sh -d foo/bar/zoo/andsoforth
Este script é usado por autoconf
e automake
project. Eu acho que deve ser a solução mais segura.
Na época, eu estava pesquisando soluções de plataforma cruzada para o padrão /bin/sh
sem dependências, mas não encontrei nenhuma. Por isso, escrevi o próximo script que pode não ser ideal, mas acho que é compatível com a maioria dos requisitos de várias plataformas :
#! /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#\(.\)/$##' -e 's#^[^/]*$#.#' -e 's#\(.\)/[^/]*$##' -
}
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
}
Este script pode ser usado para sistemas antigos, onde a opção -p
para mkdir
está ausente.
sed
com base em % de dirname
foi adicionada ao código. Ele funciona de maneira semelhante a dirname
(correto com o caminho /
, caminhos com apenas o nome base, caminhos com% /
, caminhos com e sem \n
s). Essa função não pode funcionar corretamente se o caminho tiver novas linhas ou alguns caracteres inválidos para a localidade atual. Ele também substitui qualquer combinação de /
( //
, ///
) por /
Linha alterada mkdir "$1" || return 1
to test -d "$1" || { mkdir "$1" || return 1; }
porque mkdir
termina com erro se o caminho existir e essa verificação for necessária para caminhos contendo construções como aaa\.
(Se aaa
não existir, a versão anterior cria aaa
e depois tenta criá-lo novamente).
Esta versão do mkd não gera erro se o caminho já existir (mas ainda tem a possibilidade de gerar tal erro na execução paralela) e não pode obter vários diretórios na linha de comando.
Opção -p
no comando mkdir
torna p diretórios conforme necessário (nenhum erro se existir):
mkdir -p foo/bar/zoo/andsoforth
Outra forma é, por exemplo, usar &&
(erro se a pasta especificada existir):
mkdir foo && mkdir foo/bar && mkdir foo/bar/zoo && mkdir foo/bar/zoo/andsoforth
O operador de encadeamento &&
é usado para encadear comandos juntos, de modo que o próximo comando seja executado se, e somente se, o comando anterior sair sem erros.
Claro, a primeira maneira é melhor.
mkdir foo foo/bar foo/bar/zoo/ foo/bar/zoo/andsofort.
Isso deve ser feito.
Tags mkdir