Copie a estrutura da pasta (sem arquivos) de um local para outro

94

Quero criar um clone da estrutura de nosso servidor de arquivos de vários terabytes. Eu sei que cp --parents pode mover um arquivo e sua estrutura pai, mas existe alguma maneira de copiar a estrutura de diretório intacta?

Eu quero copiar para um sistema Linux e nosso servidor de arquivos é CIFS montado lá.

r00fus
fonte
1
Possível duplicata de Rsync como incluir diretórios, mas não arquivos?
Trevor Boyd Smith
A solução rsync da postagem do comentário acima parece mais organizada.
YE

Respostas:

158

Você poderia fazer algo como:

find . -type d > dirs.txt

para criar a lista de diretórios, então

xargs mkdir -p < dirs.txt

para criar os diretórios no destino.

Greg Hewgill
fonte
8
Esta solução não funcionará se você tiver espaços nos nomes dos seus diretórios.
Jealie
29
@Jealie Altere os comandos para find . -type d -print0 >dirs.txte xargs -0 mkdir -p <dirs.txt. Isso fará com que ambos os comandos usem nulos como separadores em vez de espaços em branco.
user1207177
3
xargspode exceder o comprimento máximo do comando do sistema quando você começar a lidar com pedidos de centenas ou milhares, portanto, use isso com cuidado. (Encontre o limite de comprimento do comando com getconf ARG_MAX.) Com vários diretórios, pode ser necessário escrever um script para percorrer a saída.
palswim
1
E as permissões e atributos serão retidos ??
Ashish Karpe de
3
@TrevorBoydSmith: Obrigado pelo seu comentário. A pergunta original não mencionou nada sobre a necessidade de preservar permissões, propriedade ou atributos. Fazer isso exigiria uma solução diferente, como você mencionou, mas o acima é suficiente para responder à pergunta conforme colocada.
Greg Hewgill
79
cd /path/to/directories &&
find . -type d -exec mkdir -p -- /path/to/backup/{} \;
anfetamáquina
fonte
3
Melhor resposta minha com encontrar. Caso contrário, você pode tentar a rsyncsolução da resposta de Chen Levy nesta pergunta do SO
Mat M
3
O que significa a opção - mkdir?
Bruce_Warrior
9
--é um terminador de opção de utilitário GNU padrão. Significa "ei mkdir, qualquer argumento depois disso não é um sinalizador, então trate-o como um argumento de arquivo, mesmo que comece com um caractere '-'."
anfetamáquina
4
esta resposta também não retém as permissões e atributos do diretório . Use rynsc para preservar as permissões e atributos
Trevor Boyd Smith
35

Aqui está uma solução simples usando rsync:

rsync -av -f"+ */" -f"- *" "$source" "$target"
  • uma linha
  • sem problemas com espaços
  • preservar permissões

Eu encontrei essa solução lá

Gildas
fonte
10
mesmo, mas mais legívelrsync -a --include '*/' --exclude '*' "$source" "$target"
Sylvain
1
O problema com esta solução é: minhas pastas contêm milhares de arquivos e o rsync leva muito tempo apenas para sincronizar uma dúzia de pastas.
Christopher K.
6

Não sei se você está procurando uma solução no Linux. Se sim, você pode tentar isto:

$ mkdir destdir
$ cd sourcedir
$ find . -type d | cpio -pdvm destdir
zerodin
fonte
cpio não parece funcionar para mim, pelo menos com os parâmetros que você especificou.
r00fus
@ r00fus - leia o manual do cpio ou consulte gnu.org/software/cpio
zerodin
6

Isso copia os diretórios e atributos de arquivos, mas não os dados dos arquivos:

cp -R --attributes-only SOURCE DEST

Em seguida, você pode excluir os atributos dos arquivos se não estiver interessado neles:

find DEST -type f -exec rm {} \;
Toliveira
fonte
1
Seria excelente, mas você se esqueceu de mencionar salvar propriedade, carimbo de data / hora e permissões. Portanto, isso produziu uma bagunça no usuário Win7 / cygwin - NULL_SID, ordem de permissão errada, não é possível editar permissões, etc. e não pode acessar a estrutura de arquivos produzida.
WebComer
1
Devo pensar que a culpa é inteiramente de quem tenta usar o Windows para um trabalho real.
tripleee
cp -R --attributes-only --preserve = all --parents -v SOURCE DEST
Gábor
2

A seguinte solução funcionou bem para mim em vários ambientes:

sourceDir="some/directory"
targetDir="any/other/directory"

find "$sourceDir" -type d | sed -e "s?$sourceDir?$targetDir?" | xargs mkdir -p
yaccob
fonte
2

Isso funciona:

find ./<SOURCE_DIR>/ -type d | sed 's/\.\/<SOURCE_DIR>//g' | xargs -I {} mkdir -p <DEST_DIR>"/{}"

Basta substituir SOURCE_DIR e DEST_DIR.

mijhael3000
fonte
2

Isso resolve até mesmo o problema dos espaços em branco:

No diretório original / fonte:

find . -type d -exec echo "'{}'" \; > dirs2.txt

em seguida, recrie-o no diretório recém-criado:

mkdir -p <../<SOURCEDIR>/dirs2.txt
Thim
fonte
1

Substitua target_dire source_dircom os valores apropriados:

cd target_dir && (cd source_dir; find . -type d ! -name .) | xargs -i mkdir -p "{}"

Testado em OSX + Ubuntu.

luissquall
fonte
0

Um script python de Sergiy Kolodyazhnyy postado em Copiar somente pastas, não arquivos? :

#!/usr/bin/env python
import os,sys
dirs=[ r for r,s,f in os.walk(".") if r != "."]
for i in dirs:
    os.makedirs(os.path.join(sys.argv[1],i)) 

ou da casca:

python -c 'import os,sys;dirs=[ r for r,s,f in os.walk(".") if r != "."];[os.makedirs(os.path.join(sys.argv[1],i)) for i in dirs]' ~/new_destination

PARA SUA INFORMAÇÃO:

Franck Dernoncourt
fonte
0

Outra abordagem é usar o, treeque é muito útil e navegar em árvores de diretório com base em suas opções fortes. Existem opções apenas para diretório, excluir diretórios vazios, excluir nomes com padrão, incluir apenas nomes com padrão, etc. Check outman tree

Vantagem : você pode editar ou revisar a lista, ou se você fizer muitos scripts e criar um lote de diretórios vazios com frequência

Abordagem : crie uma lista de diretórios usando tree, use essa lista como uma entrada de argumentos paramkdir

tree -dfi --noreport > some_dir_file.txt

-dfi lista apenas diretórios, imprime o caminho completo para cada nome, faz com que a árvore não imprima as linhas de recuo,

--noreport Omite a impressão do relatório de arquivo e diretório no final da lista da árvore, apenas para fazer com que o arquivo de saída não contenha nenhum erro.

Em seguida, vá para o destino onde deseja os diretórios vazios e execute

xargs mkdir < some_dir_file.txt
irmão-bilo
fonte
0
find source/ -type f  | rsync -a --exclude-from - source/ target/

Copiar dir apenas com permissão e propriedade associadas

Tiger peng
fonte
0

Solução de 1 linha:

find . -type d -exec mkdir -p /path/to/copy/directory/tree/{} \;
Igor
fonte
-1

Se você pode obter acesso de uma máquina Windows, você pode usar xcopy com / T e / E para copiar apenas a estrutura de pastas (o / E inclui pastas vazias)

http://ss64.com/nt/xcopy.html

[EDITAR!]

Este usa rsync para recriar a estrutura do diretório, mas sem os arquivos. http://psung.blogspot.com/2008/05/copying-directory-trees-with-rsync.html

Pode até ser melhor :)

dotalquimia
fonte
1
Infelizmente, nosso servidor de arquivos de serviço CIFS não está executando o Windows, portanto, nenhum pode fazer nos comandos do Win.
r00fus
Obrigado, o método rsync funcionou perfeitamente bem para mim. É compatível com espaços em nomes de diretório também.
Glutanimato
-1

Aqui está uma solução em php que:

  • copia os diretórios (não recursivamente, apenas um nível)
  • preserva permissões
  • ao contrário da solução rsync, é rápido mesmo com diretórios contendo milhares de arquivos, pois nem mesmo vai para as pastas
  • não tem problemas com espaços
  • deve ser fácil de ler e ajustar

Crie um arquivo como syncDirs.phpcom este conteúdo:

<?php
foreach (new DirectoryIterator($argv[1]) as $f) {
    if($f->isDot() || !$f->isDir()) continue;
        mkdir($argv[2].'/'.$f->getFilename(), $f->getPerms());
        chown($argv[2].'/'.$f->getFilename(), $f->getOwner());
        chgrp($argv[2].'/'.$f->getFilename(), $f->getGroup());
}

Execute-o como um usuário com direitos suficientes:

sudo php syncDirs.php /var/source /var/destination

Christopher K.
fonte
Você não precisa gostar de PHP e não precisa usá-lo. Mas o OP não especificou se ele deseja uma solução em alguma linguagem específica e, gostando ou não, o PHP é instalado de qualquer maneira em muitos sistemas Linux já que 80% da web usa PHP ( w3techs.com/technologies/details/pl- php / all / all ).
Christopher K.