Como eu crio um diretório em todos os subdiretórios?

29

Suponha que eu tenha uma estrutura de diretórios como esta:

$ [~/practice] ls
a/ b/ c/ d/

Agora eu quero criar um diretório tmp1 em todos os subdiretórios de practice e eu faço isso:

$ [~/practice] mkdir */tmp1
mkdir: cannot create directory '*/tmp1': No such file or directory

Então, tento a opção -p e termino com um diretório chamado * com um subdiretório tmp1

$ [~/practice] mkdir -p */tmp1

$ [~/practice] ls
*/ a/ b/ c/ d/

Eu sei que o uso da opção -p é criar vários diretórios inexistentes. Eu apenas pensei que poderia ajudar.

Como faço para criar tmp1 em todos os subdiretórios de uma só vez?

Se isso puder ser feito, como estendê-lo para criar \tmp1 , \tmp2 , \tmp3 em \a , \b e \c de uma só vez?

Edit: Eu esqueci de mencionar que os diretórios não precisam ser simples e ordenados, como a , b , c etc., e o diretório a ser criado não é necessariamente como tmp1 , tmp2 .

$ [~/practice] ls
dog/ cat/ rat/

Neles, gostaria de ter algo parecido com

$ [~/practice] ls *
dog:
red/ blue/

cat:
red/ blue/

rat:
red/ blue/
    
por Animesh 20.01.2013 / 16:08

10 respostas

39

Com globs :

for dir in */; do mkdir -- "$dir/tmp1"; done

NOTA

  • Eu trato apenas dirs (incluindo links simbólicos para dirs) com o pequeno hack de usar */ como glob
  • Se você deseja criar vários subdiretórios de uma só vez:

    for dir in */; do mkdir -- "$dir"/{tmp1,foo,bar,qux}; done

por 20.01.2013 / 16:10
10

[...] how do I extend it to create \tmp1, \tmp2, \tmp3 in \a, \b and \c at once?

 mkdir {a,b,c}/tmp{1,2,3}
    
por 20.01.2013 / 16:21
10

Com GNU ou BSD *, ache:

find -mindepth 1 -maxdepth 1 -type d -exec mkdir {}/newdir \;

ou usando a expansão de parâmetros:

dirs=(*/)
mkdir -- "${dirs[@]/%/newdir}"

* Inclui o OS X

    
por 20.01.2013 / 22:09
6

Off topic, já que você está mencionando bash , mas para o registro, com zsh, você faria:

dirs=(*(/))
mkdir -- $^dirs/tmp1

$^var ativa a expansão brace-like para a expansão da matriz. É uma reminiscência do operador rc ^ e em rc (ou seu derivado es ), você escreveria:

dirs=(*/)
mkdir -- $dirs^tmp1

No entanto note (e o mesmo se aplica às soluções bash dadas aqui) que na solução rc dirs também conteria links simbólicos para diretórios. Na solução zsh, altere *(/) para *(-/) se você quiser incluir links simbólicos em diretórios.

    
por 20.01.2013 / 21:13
4

Portável, faça um loop pelos diretórios principais:

for d in */; do mkdir "$d/red" "$d/blue"; done

Adicione -- após mkdir se você tiver diretórios cujo nome comece com - .

Em zsh, você pode fazer isso em um único comando com o qualificador de glob e :

mkdir *(/e\''REPLY=($REPLY/{red,blue})'\')

mas é mais rápido digitar isso como dois comandos:

d=(*(/)); mkdir $^d/{red,blue}
    
por 21.01.2013 / 01:52
1

Você pode fazer isso assim:

mkdir {a,b,c,d}/tmp1
    
por 20.01.2013 / 16:18
1

Variação na resposta do sputnick que evita arquivos que não são de diretório:

for x in *; do if [ -d "$x" ]; then mkdir "$x/tmp1"; fi; done
    
por 20.01.2013 / 16:17
1

Este é um bom exemplo do antigo Unix Masters (testado no FreeBSD 10.1) se você quiser controlar a versão (com RCS check in bloqueado: ci -l com um breve comentário como ir: para o lançamento inicial) seu arquivo / etc / * arquivos de configuração em ~ / .his / etc

sudo rsync -av /etc/ ~/.his
sudo find -d ~/.his/etc -type d -exec echo '{}/RCS' \; | xargs sudo mkdir -p
sudo find -d ~/.his/etc \! -name "RCS" | xargs sudo ci -l -mir -t-ir
    
por 28.03.2015 / 07:45
1

Deve ser \! nome "RCS" e funciona melhor no primeiro check in.

sudo find ~ / .his / etc \! -nome "RCS" -ls

sudo encontre -d ~ / .his / etc \! -nome "RCS" | xargs sudo ci -irmir -t-ir

Este último também funciona muito bem para o cjeck em parte filtrando todo o conteúdo RCS no nome do arquivo:

sudo find -d ~ / .his / etc -tipo f | grep -v RCS | xargs sudo ci -irmir -t-ir

    
por 28.03.2015 / 07:48
1

isso é uma grande ajuda para mim. Eu tive a necessidade de criar um conjunto de subdiretórios em várias pastas e algo como:

!/bin/sh

cd /dest/cont

for dir in */*/; do
    mkdir -p -- $dir/{FB,Video,Audio,proj};
done

funcionou bem, exceto quando um espaço em branco é encontrado. Existe uma maneira de ignorar espaços na parte */*/ dos argumentos?

    
por 28.03.2015 / 18:22