mkdir -p para arquivos

20

mkdir -p criará um diretório; ele também fará diretórios pais conforme necessário.

Existe um comando similar para arquivos, que criarão um arquivo e diretórios pai conforme necessário?

    
por Steven Penny 30.01.2013 / 10:09

6 respostas

27

A instalação fará isso, se receber o arquivo de origem /dev/null . O argumento -D diz para criar todos os diretórios pais:

anthony@Zia:~$ install -D /dev/null /tmp/a/b/c
anthony@Zia:~$ ls -l /tmp/a/b/c 
-rwxr-xr-x 1 anthony anthony 0 Jan 30 10:31 /tmp/a/b/c

Não tenho certeza se isso é um bug ou não - seu comportamento com arquivos de dispositivos não é mencionado na página do manual. Você também pode simplesmente fornecer um arquivo em branco (recém-criado com mktemp , por exemplo) como a origem.

    
por 30.01.2013 / 16:34
7

Não, não tanto quanto eu sei. Mas você sempre pode usar mkdir -p e touch após o outro:

f="/a/b/c.txt"
mkdir -p -- "${f%/*}" && touch -- "$f"
    
por 30.01.2013 / 10:12
2

Eu frequentemente encontrei esse tipo de situação, então eu simplesmente escrevi uma função no meu arquivo .bashrc . Parece que isso

function create() {
    arg=$1
    num_of_dirs=$(grep -o "/" <<< $arg | wc -l)
    make_dirs=$(echo $arg | cut -d / -f1-$num_of_dirs)
    mkdir -p $make_dirs && touch $arg
}

Então, quando eu quero criar um arquivo dentro de um caminho de diretórios inexistentes, direi

create what/is/it  # will create dirs 'what' and 'is', with file 'it' inside 'is'
    
por 26.08.2016 / 09:23
0
dir=$(dirname "$f")
test -d $dir || mkdir -p "$dir"
    
por 30.01.2013 / 15:36
0

Eu ia sugerir, pois isso o mantém em uma linha, embora a configuração da variável separadamente permita que você a altere e reexecute facilmente o comando do histórico.

B="./make/this/path" && mkdir -p -- "$B" && touch -- "$B/file.txt"
    
por 30.01.2013 / 10:21
0

É possível "fingir".

Primeiro, alguma teoria obrigatória:

Rob Griffiths postou um artigo em 2007 intitulado Crie facilmente muitas novas pastas no Macworld.com, onde ele discutiu o uso do comando xargs para ler em uma lista de arquivos para criar diretórios usando mkdir .

xargs é capaz de fazer referência a um placeholder ( {} ) com o sinal -I , que contém o valor para cada argumento passado para xargs . Aqui está a diferença entre esse sinalizador e sem:

$ foo.txt bar.txt | xargs echo
$ => foo.txt bar.txt
$ foo.txt bar.txt | xargs -I {} echo {}
$ => foo.txt
$ => bar.txt

xargs também é capaz de executar comandos shell arbitrários com o sinalizador sh -c :

foo.txt bar.txt | xargs sh -c 'echo arbitrary command!'

Combinando os conceitos:

Podemos combinar esses conceitos com mkdir -p em vez de mkdir e o conceito em @ldx ' s responda para produzir isto:

$ cat files.txt | xargs -I {} sh -c 'f="{}" && mkdir -p -- "${f%/*}" && touch -- "$f"'

Esse comando basicamente mapeia cada nome de arquivo em uma lista separada por linhas de arquivos, corta a parte do arquivo, cria os diretórios com mkdir -p e, em seguida, touch es o nome do arquivo em seu respectivo diretório.

Veja um resumo do que acontece no comando acima:

Digamos, por exemplo, que meu files.txt seja assim:

deeply/nested/foo/bar.txt
deeply/nested/baz/fiz.txt
  • cat files.txt produz deeply/nested/foo/bar.js deeply/nested/baz/fiz.txt
  • deeply/nested/foo/bar.js deeply/nested/baz/fiz.txt é canalizado para xargs
  • porque usamos -I {} , xargs irá traduzir cada argumento para seu próprio comando, então agora temos:
    • deeply/nested/foo/bar.txt
    • deeply/nested/baz/fiz.txt
  • em seguida, executamos um comando shell que usa o && combinator para os comandos do grupo 3 que são executados sequencialmente - o primeiro comando armazena o arquivo em uma variável de ambiente (que é reutilizada na próxima passagem de arquivo) usando o espaço reservado we registrado antes, então agora temos:
    • f=deeply/nested/foo/bar.txt
    • f=deeply/nested/baz/fiz.txt
  • agora temos uma variável que podemos passar para mkdir -p , mas precisamos cortar o nome do arquivo. Simples o suficiente usando '${f%/*}' :
    • mkdir -p deeply/nested/foo/
    • mkdir -p deeply/nested/baz/
  • e, em seguida, apenas re-referenciamos a variável f em sua totalidade quando touch :
    • touch deeply/nested/foo/bar.txt
    • touch deeply/nested/baz/fiz.txt
por 10.03.2016 / 15:50