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

34

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

$ [~ / prática] ls
a / b / c / d /

Agora eu quero criar um diretório tmp1em todos os subdiretórios practicee faço isso:

$ [~ / practice] mkdir * / tmp1
mkdir: não é possível criar o diretório `* / tmp1 ': esse arquivo ou diretório não existe

Então eu tento o -pswitch e termino com um diretório nomeado *com um subdiretóriotmp1

$ [~ / prática] mkdir -p * / tmp1

$ [~ / prática] ls
* / a / b / c / d /

Eu sei que o uso do -pswitch é criar vários diretórios inexistentes. Eu apenas pensei que poderia ajudar.

Como crio tmp1em todos os subdiretórios de uma só vez?

Se isso pode ser feito, como faço para estendê-lo para criar \tmp1, \tmp2, \tmp3em \a, \be \cao mesmo tempo?

Edit: eu perdi mencionar que os diretórios não tem que ser simples e em ordem, como a, b, cetc., e o diretório a ser criado não é necessariamente como tmp1, tmp2.

$ [~ / prática] ls
cão / gato / rato /

Neles, eu gostaria de ter algo como

$ [~ / prática] ls *
cachorro:
vermelho azul/

gato:
vermelho azul/

rato:
vermelho azul/
Animesh
fonte
11
Dada a resposta de Christopher , você deve esclarecer se "criar \ tmp1, \ tmp2, \ tmp3 em \ a, \ be \ c" deve resultar em um total de 3 ou 9 subdiretórios.
precisa saber é
@ manatwork: Esse é um bom ponto. Ele deve criar 9 subdiretórios.
Animesh
Esta é minha ajuda para resolver o problema de espaço no nome do diretório sudo find ./ -thp -type d -exec echo '"{} / RCS"' \;

Respostas:

44

Com globs :

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

NOTA

  • Trato apenas dirs (incluindo links simbólicos para dirs) com o pequeno truque de usar */como um glob
  • Se você deseja criar vários subdiretórios ao mesmo tempo:

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

Gilles Quenot
fonte
Eu poderia fazer for i in */; do mkdir "$i/itemone" "$i/itemtwo"; donepor vários nomes de diretório não em ordem?
Animesh
Eu testei isso e é muito possível. Obrigado.
Animesh
Veja meu post editado
Gilles Quenot,
11
A expansão de chaves não é executada na cadeia de caracteres entre aspas.
manatwork
Sim, obrigado, post editado por Stephane Chazelas conformidade ...
Gilles Quenot
10

[...] como eu o estendo para criar \ tmp1, \ tmp2, \ tmp3 em \ a, \ be \ c de uma só vez?

 mkdir {a,b,c}/tmp{1,2,3}
Christopher
fonte
10

Com o GNU ou BSD *, encontre:

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

ou usando expansão de parâmetro:

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

* Inclui OS X

kojiro
fonte
2
Com sintaxe de localização padrão:find . -name . -o -prune -type d -exec sh -c 'exec mkdir "$1/newdir"' sh {} \;
Stéphane Chazelas
11
Observe também as diferenças entre as duas soluções: a primeira inclui diretórios ocultos, a segunda adicionará um newdir nos diretórios vinculados por qualquer link simbólico no diretório atual.
Stéphane Chazelas
6

Fora do tópico desde que você está mencionando bash, mas para o registro, com o zsh, você faria:

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

$^varativa a expansão tipo braquete para a expansão da matriz. É uma reminiscência de rc's ^operador e rc(ou seus derivados es), você escrevê-lo:

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

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

Stéphane Chazelas
fonte
+1 pelo seu ponto sobre links simbólicos! Esse comportamento pode ser desejado, mas a reclamação do mkdir sobre a criação de um diretório duplicado pode ser suprimida com o -psinalizador.
usar o seguinte comando
4

Portably, faça um loop nos diretórios pai:

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

Adicione --depois mkdirse você tiver diretórios cujo nome comece com -.

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

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

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

d=(*(/)); mkdir $^d/{red,blue}
Gilles 'SO- parar de ser mau'
fonte
11
Em um site que deve ser uma referência, prefiro dizer " mkdir -- whatevere omitir -- se você pretende expandir o que quer que possa ser tomado como opção para o mkdircomando". Não faz sentido omitir --aqui. Pode não ser um problema no caso do OP, mas é um no caso geral. Acho que temos o dever de ensinar a sintaxe correta e segura aqui.
Stéphane Chazelas
@StephaneChazelas Em um contexto de script, eu sempre coloco todos os --avisos necessários e citados e grandes avisos quando as novas linhas não são suportadas. Em um contexto de linha de comando, prefiro mostrar a versão rápida que funciona primeiro na prática e a versão à prova de balas como complemento.
Gilles 'SO- stop be evil'
1

Você pode fazer isso assim:

mkdir {a,b,c,d}/tmp1
ДМИТРИЙ МАЛИКОВ
fonte
11
E se ele tiver 100 diretórios?
Bernhard
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
Cachinhos Dourados
fonte
I tratar apenas dirs, que "é toda a magia ...
Gilles Quenot
legal, entendi;)
goldilocks
2
Não deveria ser if [ -d "$x" ];…?
usar o seguinte comando
Sim. Eu praticamente nunca tem espaços em nomes de arquivos e tendem a esquecer essas coisas ...
Goldilocks
1

Esta é uma boa versão do antigo Unix Masters (testado no FreeBSD 10.1) se você deseja controlar a versão (com o RCS bloqueado: ci -l com um breve comentário como ir: para o lançamento inicial) seus arquivos de configuração / etc / * 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
user108341
fonte
Eu não consigo ver como esta resposta do OP
Archemar
1

Deveria estar \! nomeie "RCS" e funcionará melhor no primeiro check-in.

sudo encontrar ~ /. his / etc \! -name "RCS" -ls

sudo encontrar -d ~ /. his / etc \! -name "RCS" | xargs sudo ci -l -mir -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 -l -mir -t-ir

user108341
fonte
1

isso é uma grande ajuda para mim. Eu precisava 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?

johno
fonte