Copiar apenas pastas, não arquivos?

16

Existe uma maneira de copiar um diretório inteiro, mas apenas as pastas? Eu tenho um arquivo corrompido em algum lugar do meu diretório que está causando falhas nos meus discos rígidos.

Então, em vez de copiar o arquivo corrompido para outro disco rígido, eu queria apenas copiar as pastas, porque tenho scripts que pesquisam centenas de pastas e não quero criar manualmente todas elas.

Pesquisei o manual do cp, mas não consegui ver nada (posso ter perdido)

Digamos que eu tenha essa estrutura no disco rígido com falha:

dir1
    files
    dir2
        files
        files
        dir4
dir3
files

Tudo o que eu quero é a estrutura de diretórios, nenhum arquivo.

Então, eu terminaria com o novo HDD:

dir1
    dir2
        dir4
dir3

Esperando que alguém conheça alguns truques!

Shannon
fonte
Você quer apenas copiar a estrutura do diretório ou apenas excluir os arquivos no diretório de trabalho atual (e todos os outros arquivos em subdiretórios mais profundos são jogos)?
Oli
Eu adicionei um exemplo. desculpe por ser confuso #
Shannon
11
Para sua informação, rsynccopie a estrutura de diretórios E mantenha as permissões e os atributos] ( stackoverflow.com/a/9242883/52074 ). O uso da planície mkdir -p não preserva permissões e atributos .
Trevor Boyd Smith

Respostas:

15

Se você deseja espelhar um esqueleto de diretório e copiar nenhum arquivo:

find -type d -links 2 -exec mkdir -p "/path/to/backup/{}" \;

O que está acontecendo aqui:

  • Localizar está apenas selecionando diretórios
  • Estamos usando -links 2para encontrar os diretórios mais profundos possíveis .
  • mkdir -p fará todos os diretórios ausentes ao longo do caminho.

Eu fiz isso dessa maneira, e não find -type d -exec mkdir -p "/path/to/backup/{}" \;porque isso interrompe uma quantidade enorme de mkdirchamadas. Podemos provar isso rapidamente com um pequeno teste. Aqui está a árvore de teste seguida pelo que corri para comparar os dois comandos:

$ tree
.
├── dir1
│   ├── dir2
│   │   └── dir3
│   ├── dir7
│   └── dir8
└── dir9
    └── dir0

$ pr -m -t <(find -type d) <(find -type d -links 2)
.                               ./dir1/dir8
./dir1                          ./dir1/dir2/dir3
./dir1/dir8                     ./dir1/dir7
./dir1/dir2                     ./dir9/dir0
./dir1/dir2/dir3
./dir1/dir7
./dir9                  
./dir9/dir0 

E isso só vai melhorar em uma solução de palavras reais com milhares de diretórios.

Oli
fonte
Estou sendo um noob, no entanto, como você está pesquisando no diretório antigo para copiar para o backup? Eu só posso ver um caminho aqui #
Shannon
Se você não especificar um caminho, findusa o diretório de trabalho atual como ponto de partida. Se você deseja usar outro caminho, use a sintaxe:find /path/to/search/ -type.....
Oli
Então, defino meu diretório para uma determinada pasta que contém o esqueleto que quero copiar, executar find -type d -exec mkdir -p "/media/jinglez/TVSeries/TV Series"/{}" \;e tudo deve ficar bem? Parece estar demorando um pouco: /
Shannon
Eu corro isso do terminal normal certo?
Shannon
11
Ambos são específicos da cláusula exec da find. {} significa o nome do arquivo "encontrado" atual e \; é apenas a fuga para terminar a cláusula. Pelo que parece, há um extra "no seu código que não é bom, tenho certeza ... Deveria ler:find -type d -links 2 -exec mkdir -p "/media/jinglez/TVSeries/TV Series/{}" \;
Oli
2

Muito fácil de fazer com o linux python:

bash-4.3$ tree
.
├── ABC
├── set_pathname_icon.py
├── subdir1
│   ├── file1.abc
│   └── file2.abc
├── subdir2
│   ├── file1.abc
│   └── file2.abc
└── subdir3
    └── subdir4
        └── file1.txt

4 directories, 7 files
bash-4.3$ 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
bash-4.3$ tree ~/new_destination
/home/xieerqi/new_destination
├── subdir1
├── subdir2
└── subdir3
    └── subdir4

Como script, isso pode ser reescrito da seguinte maneira:

#!/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)) 
Sergiy Kolodyazhnyy
fonte