mkdir recursivo

247

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?

    
por Braiam 07.08.2012 / 22:34

4 respostas

415
$ mkdir -p foo/bar/zoo/andsoforth
    
por 07.08.2012 / 22:35
13

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.

A versão de plataforma cruzada 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.

    
por 18.04.2016 / 00:45
0

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.

    
por 18.04.2018 / 22:32
-3
mkdir foo foo/bar foo/bar/zoo/ foo/bar/zoo/andsofort.

Isso deve ser feito.

    
por 20.12.2017 / 08:00

Tags