Skopiować tylko foldery, a nie pliki?


16

Czy istnieje sposób na skopiowanie całego katalogu, ale tylko folderów? Mam gdzieś w katalogu uszkodzony plik, który powoduje awarię dysków twardych.

Zamiast kopiować uszkodzony plik na inny dysk twardy, chciałem po prostu skopiować foldery, ponieważ mam skrypty wyszukujące setki folderów i nie chcę ręcznie tworzyć ich wszystkich.

Przeszukałem instrukcję cp, ale nic nie widziałem (mogłem to przegapić)

Powiedzmy, że mam tę strukturę na moim uszkodzonym dysku twardym:

dir1
    files
    dir2
        files
        files
        dir4
dir3
files

Chcę tylko struktury katalogów, a nie żadnych plików.

Skończyło się na nowym dysku twardym:

dir1
    dir2
        dir4
dir3

Mam nadzieję, że ktoś zna jakieś sztuczki!


Czy masz na myśli, że chcesz po prostu skopiować strukturę katalogu, czy po prostu chcesz wykluczyć pliki z bieżącego katalogu roboczego (a wszystkie inne pliki w głębszych podkatalogach są grą)?
— Oli

Dodałem przykład. przepraszam za mylące
— Shannon,

1
FYI służy rsyncdo kopiowania struktury katalogów ORAZ zachowania uprawnień i atrybutów] ( stackoverflow.com/a/9242883/52074 ). Używanie zwykłego mkdir -p nie zachowuje uprawnień i atrybutów .
— Trevor Boyd Smith

Odpowiedzi:


15

Jeśli chcesz wykonać kopię lustrzaną szkieletu katalogu i nie kopiować żadnych plików:

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

Co tu się dzieje:

  • Znajdź to tylko wybieranie katalogów
  • Używamy, -links 2aby znaleźć najgłębsze możliwe katalogi .
  • mkdir -p utworzy po drodze brakujące katalogi.

Zrobiłem to w ten sposób, a nie find -type d -exec mkdir -p "/path/to/backup/{}" \;dlatego, że ograniczy to cały zestaw mkdirpołączeń. Możemy to szybko udowodnić za pomocą małego testu. Oto drzewo testowe, a następnie to, co uruchomiłem, aby porównać dwa polecenia:

$ 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 

A to tylko poprawi się w rozwiązaniu opartym na prawdziwych słowach z tysiącami katalogów.


To ja jestem noobem, ale jak przeszukujesz stary katalog, aby skopiować do kopii zapasowej? Widzę tu tylko jedną ścieżkę
— Shannon,

Jeśli nie określisz ścieżki, findużyje bieżącego katalogu roboczego jako punktu początkowego. Jeśli chcesz użyć innej ścieżki, użyj składni:find /path/to/search/ -type.....
— Oli

Więc ustawiłem mój katalog na określony folder zawierający szkielet, który chcę skopiować, uruchomić find -type d -exec mkdir -p "/media/jinglez/TVSeries/TV Series"/{}" \;i wszystko powinno być w porządku? Wydaje się, że zajmuje to trochę czasu: /
— Shannon

Uruchamiam to z normalnego terminala, prawda?
— Shannon,

1
Oba są specyficzne dla klauzuli exec find. {} oznacza bieżącą „znalezioną” nazwę pliku i \; jest tylko ucieczką do zakończenia klauzuli. Wygląda na to, że w kodzie znajduje się dodatkowy „do niczego dobrego, jestem pewien ... Powinien przeczytać:find -type d -links 2 -exec mkdir -p "/media/jinglez/TVSeries/TV Series/{}" \;
— Oli

2

Całkiem łatwo zrobić z python one-liner:

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

Jako skrypt można to przepisać w następujący sposób:

#!/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)) 
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.