Crie as mesmas subpastas em outra pasta

8

Eu tenho um diretório foocom subdiretórios. Desejo criar os mesmos nomes de subdiretórios em outro diretório sem copiar seu conteúdo. Como eu faço isso?

Existe uma maneira de obter lssaída como uma lista de expansão de chaves?

havakok
fonte

Respostas:

11

Tente isso,

cd /source/dir/path
find . -type d -exec mkdir -p -- /destination/directory/{} \;
  • . -type d Para listar diretórios no caminho atual recursivamente.
  • mkdir -p -- /destination/directory/{} criar diretório no destino.

Isso se baseia em um findque suporta expansão {}no meio de uma palavra de argumento.

Siva
fonte
6
Isso pode ser interrompido se qualquer nome de arquivo ou pasta no nível superior começar com um traço. Também omite diretórios que começam com um ponto. Por fim, esteja ciente de que nem toda implementação de findsuporta a interpolação de {}em outra sequência.
roaima 23/09/19
11
E não é muito escalável - levará muito tempo se houver milhões de diretórios.
Arkadiusz Drabczyk 23/09/19
6
Se há muitas coisas em /source/dir/path, então este poderá falhar com uma "lista de argumentos muito longa" erro quando as tentativas de shell para chamar findcom a expansão da *. Melhor usar apenas .lá. Além disso, a maioria das findimplementações permite {}ser usada mesmo quando concatenada com outra sequência, mas não é universal.
Kusalananda
11
Você pode usar .Em vez de *neste caso. (Usando xarg para desempenho e segurança provavelmente exigiria um script externo para a concatenação path)
Eckes
24

Usando rsync:

rsync -a --include='*/' --exclude='*' /some/path/dir/ dir

Isso recriaria a estrutura de diretórios /some/path/dircomo dirno diretório atual, sem copiar nenhum arquivo.

Qualquer diretório encontrado no caminho de origem seria criado no destino devido ao padrão de inclusão, mas qualquer outra coisa seria excluída. Como efeito colateral do uso de -a( --archive), você obterá os mesmos carimbos de data e hora em todos os subdiretórios no destino e na origem. Isso também funciona para criar estruturas de diretórios locais a partir de diretórios remotos (e vice-versa).

Kusalananda
fonte
A resposta é quase sempre rsync!
Arronical 24/09/19
8

Você pode usar findpara percorrer a estrutura de origem e chamar mkdircada diretório que ele atender.

Este exemplo, usando find, copiará sua estrutura de diretórios de foopara/tmp/another/

( cd foo && find -type d -exec sh -c 'for d do mkdir -p "/tmp/another/$d"; done' sh {} + )

O execloop cria o conjunto de diretórios abaixo foo, que é passado para o mkdir. Se você não tem uma versão finddisso, +pode usar \;ao custo da eficiência. Substitua mkdirpor echo mkdirpara ver o que aconteceria sem realmente fazê-lo.

roaima
fonte
11
Ou com o loop óbvio,... -exec sh -c 'for dirpath do mkdir -p "/some/path/$dirpath"; done' sh {} +
Kusalananda
exatamente com GNU find (4.7.0-git), este não parece trabalho: find: In ‘-exec ... {} +’ the ‘{}’ must appear by itself, but you specified ‘/tmp/another/{}’(ela não funciona com -exec ... \;, embora)
ilkkachu
Kusalananda, improvment tomadas, obrigado
roaima
Ilkkachu Tenho certeza de que testei, /path/to/{}mas agora não consigo encontrar nenhuma versão em que funcione, por isso adaptei a solução. Obrigado
roaima 26/09/19
3

Com o shell bash, você pode solicitar a expansão de todos os diretórios com a globstaropção:

shopt -s globstar

e copie os diretórios com um loop:

for dir in **/
do
  mkdir -p /path/to/dest/"$dir"
done

... ou se você acha que todos eles se encaixam em uma chamada para mkdir:

set -- **/
mkdir -- "${@/#//path/to/dest/}"

Essa é a sintaxe do bash array que diz: "pegue todos os elementos do $@array e substitua o início de cada um deles por /path/to/dest/.

Não conheço uma maneira de obter lssaída diretamente como uma lista de expansão de chaves. Se você tentou massagear a saída da **/expansão em uma expansão de cinta, seria necessário ter cuidado para:

  • escapar quaisquer vírgulas na saída
  • escapar de qualquer {ou ${sequência
  • garantir que a sequência resultante não exceda o espaço de argumento da linha de comandos disponível

Eu não recomendaria.

Jeff Schaller
fonte
2

A pergunta é uma duplicata entre sites de /superuser/1389580/copy-directory-structure-only-at-year-end

Esse tipo de tarefa é um caso de uso clássico para mtree:

$ mkdir new-tree
$ mtree -cp old-tree | mtree -tdUp new-tree
.:      modification time (Tue Sep 24 14:27:07 2019, Tue Sep 24 16:34:57 2019, modified)
./bar missing (created)
./bar/bar2 missing (created)
./bar/bar2/bar3 missing (created)
./bar/bar2/bar3/bar4 missing (created)
./foo missing (created)
./foo/foo2 missing (created)
./foo/foo2/foo3 missing (created)

O acima cria todos os diretórios abaixo new-treeque estavam presentes em old-tree. mtreenão define carimbos de data e hora em diretórios recém-criados, portanto, a árvore resultante se parece com isso:

$ find old-tree new-tree -ls
 20147  1 drwx--x---   4 jim   jim   5 Sep 24 14:27 old-tree
 20048  1 drwx--x---   3 jim   jim   4 Sep 24 14:27 old-tree/foo
 20363  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/foo/file
 20073  1 drwx--x---   3 jim   jim   4 Sep 24 14:27 old-tree/foo/foo2
 20074  1 drwx--x---   2 jim   jim   3 Sep 24 14:27 old-tree/foo/foo2/foo3
 20365  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/foo/foo2/foo3/file
 20364  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/foo/foo2/file
 20051  1 drwx--x---   3 jim   jim   4 Sep 24 14:27 old-tree/bar
 20077  1 drwx--x---   3 jim   jim   4 Sep 24 14:27 old-tree/bar/bar2
 20368  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/bar/bar2/file
 20078  1 drwx--x---   3 jim   jim   4 Sep 24 14:27 old-tree/bar/bar2/bar3
 20369  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/bar/bar2/bar3/file
 20079  1 drwx--x---   2 jim   jim   3 Sep 24 14:27 old-tree/bar/bar2/bar3/bar4
 20370  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/bar/bar2/bar3/bar4/file
 20366  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/bar/file
 20362  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/file
134489  1 drwx--x---   4 jim   jim   4 Sep 24 16:34 new-tree
134490  1 drwx--x---   3 jim   jim   3 Sep 24 16:34 new-tree/bar
134491  1 drwx--x---   3 jim   jim   3 Sep 24 16:34 new-tree/bar/bar2
134492  1 drwx--x---   3 jim   jim   3 Sep 24 16:34 new-tree/bar/bar2/bar3
134493  1 drwx--x---   2 jim   jim   2 Sep 24 16:34 new-tree/bar/bar2/bar3/bar4
134494  1 drwx--x---   3 jim   jim   3 Sep 24 16:34 new-tree/foo
134495  1 drwx--x---   3 jim   jim   3 Sep 24 16:34 new-tree/foo/foo2
134496  1 drwx--x---   2 jim   jim   2 Sep 24 16:34 new-tree/foo/foo2/foo3

Se você preferir que os new-treecarimbos de data e hora correspondam aos old-tree, simplesmente execute mtreenovamente. Como os diretórios já existem, mtreeos timestamps serão modificados para corresponder à especificação de origem:

$ mtree -cp old-tree | mtree -tdUp new-tree
.:      modification time (Tue Sep 24 14:27:07 2019, Tue Sep 24 16:34:57 2019, modified)
bar:    modification time (Tue Sep 24 14:27:07 2019, Tue Sep 24 16:34:57 2019, modified)
bar/bar2: 
        modification time (Tue Sep 24 14:27:07 2019, Tue Sep 24 16:34:57 2019, modified)
bar/bar2/bar3: 
        modification time (Tue Sep 24 14:27:07 2019, Tue Sep 24 16:34:57 2019, modified)
bar/bar2/bar3/bar4: 
        modification time (Tue Sep 24 14:27:07 2019, Tue Sep 24 16:34:57 2019, modified)
foo:    modification time (Tue Sep 24 14:27:07 2019, Tue Sep 24 16:34:57 2019, modified)
foo/foo2: 
        modification time (Tue Sep 24 14:27:07 2019, Tue Sep 24 16:34:57 2019, modified)
foo/foo2/foo3: 
        modification time (Tue Sep 24 14:27:07 2019, Tue Sep 24 16:34:57 2019, modified)
$ find old-tree new-tree -ls
 20147  1 drwx--x---   4 jim   jim   5 Sep 24 14:27 old-tree
 20048  1 drwx--x---   3 jim   jim   4 Sep 24 14:27 old-tree/foo
 20363  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/foo/file
 20073  1 drwx--x---   3 jim   jim   4 Sep 24 14:27 old-tree/foo/foo2
 20074  1 drwx--x---   2 jim   jim   3 Sep 24 14:27 old-tree/foo/foo2/foo3
 20365  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/foo/foo2/foo3/file
 20364  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/foo/foo2/file
 20051  1 drwx--x---   3 jim   jim   4 Sep 24 14:27 old-tree/bar
 20077  1 drwx--x---   3 jim   jim   4 Sep 24 14:27 old-tree/bar/bar2
 20368  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/bar/bar2/file
 20078  1 drwx--x---   3 jim   jim   4 Sep 24 14:27 old-tree/bar/bar2/bar3
 20369  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/bar/bar2/bar3/file
 20079  1 drwx--x---   2 jim   jim   3 Sep 24 14:27 old-tree/bar/bar2/bar3/bar4
 20370  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/bar/bar2/bar3/bar4/file
 20366  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/bar/file
 20362  1 -rw-------   1 jim   jim   0 Sep 24 14:27 old-tree/file
134489  1 drwx--x---   4 jim   jim   4 Sep 24 14:27 new-tree
134490  1 drwx--x---   3 jim   jim   3 Sep 24 14:27 new-tree/bar
134491  1 drwx--x---   3 jim   jim   3 Sep 24 14:27 new-tree/bar/bar2
134492  1 drwx--x---   3 jim   jim   3 Sep 24 14:27 new-tree/bar/bar2/bar3
134493  1 drwx--x---   2 jim   jim   2 Sep 24 14:27 new-tree/bar/bar2/bar3/bar4
134494  1 drwx--x---   3 jim   jim   3 Sep 24 14:27 new-tree/foo
134495  1 drwx--x---   3 jim   jim   3 Sep 24 14:27 new-tree/foo/foo2
134496  1 drwx--x---   2 jim   jim   2 Sep 24 14:27 new-tree/foo/foo2/foo3
Jim L.
fonte