Jak filtrować pliki podczas używania scp do rekurencyjnego kopiowania katalogu?

99

Muszę skopiować wszystkie pliki .class z serwera na lokalny, zachowując cały katalog zarezerwowany. np. server:/usr/some/unknown/number/of/sub/folders/me.classbędzie /usr/project/backup/some/unknown/number/of/sub/folders/me.classproblem, jest wiele innych bezużytecznych plików, takich jak pliki .svn-base, których nie chcę. jak mogę je filtrować, więc tylko scppliki .class?

derrdji
źródło
Podoba mi się wspomniana opcja rsync. Nie wspomniałeś, czy jest to jednorazowa operacja, czy też będziesz ją wielokrotnie automatyzować. W przypadku jednorazowej operacji, rozsądne użycie poleceń find, grep -v, xargs i plików tymczasowych powinno szybko załatwić sprawę.
user47559

Odpowiedzi:

152

Prawdopodobnie poleciłbym użycie czegoś takiego rsyncze względu na jego includei excludeflagi, np: -

rsync -rav -e ssh --include '*/' --include='*.class' --exclude='*' \
server:/usr/some/unknown/number/of/sub/folders/ \ 
/usr/project/backup/some/unknown/number/of/sub/folders/

Kilka innych przydatnych flag:

  • -r dla rekurencyjnych
  • -a do archiwum (głównie wszystkie pliki)
  • -v dla pełnych informacji wyjściowych
  • -e aby określić ssh zamiast domyślnego (właściwie powinno to być ssh)
Gavin Gilmour
źródło
4
W każdym razie, aby ignorować podfoldery, które nie zawierają plików * klas? (tj. nie chcę kilku pustych reżerów)
Grant Birchmeier
super, i to też jest niesamowicie szybkie!
Prasad Chalasani,
2
Czy możesz wyjaśnić --include, not --include = Na stronach MAN mogłem znaleźć wyjaśnienie na temat --include = ale nie --include
bazz
1
Zgodnie ze stronami podręcznika rsync opcja -ajuż zawiera -r.
Georg Schölly
3
@GrantBirchmeier --prune-empty-dirsusunie puste katalogi.
Elrond1337
75

Aby wykluczyć dotfiles w katalogu podstawowym:

scp -r [!.]* server:/path/to/something

[!.]* jest globalną powłoką, która rozwija się do wszystkich plików w katalogu roboczym, a nie zaczyna się od kropki.

rgtk
źródło
10
To prawdopodobnie najlepsza odpowiedź; użycie globów do filtrowania plików jest drogą do zrobienia.
Yoshua Wuyts
1
Jeśli twoja opcja jest ograniczona do scp, tak jak ja, to zdecydowanie pomogło.
user28095
3
Wskazuje to na wykluczenie plików, na przykład pytanie, ale jak można to osiągnąć dla całego katalogu?
Pille
Dla zsh:scp -r [\!.]* server:/path/to/something
Michael Bar-Sinai
37

W scp nie ma funkcji filtrowania plików. W przypadku „zaawansowanych” rzeczy, takich jak ten, zalecam użycie rsync:

rsync -av --exclude '*.svn' user@server:/my/dir .

(ta linia kopiuje rsync z odległego folderu do bieżącego)

Najnowsze wersje tunelu rsync przez połączenie ssh domyślnie automatycznie.

Ville Laurikari
źródło
10

Ponieważ możesz scp, powinieneś być w porządku ssh,
wykonaj skrypt lub zaloguj się i wykonaj ...

# After reaching the server of interest
cd /usr/some/unknown/number/of/sub/folders
tar cfj pack.tar.bz2 $(find . -type f -name *.class)

wróć (wylogowania) na serwerze lokalnym i scp,

# from the local machine
cd /usr/project/backup/some/unknown/number/of/sub/folders
scp you@server:/usr/some/unknown/number/of/sub/folders/pack.tar.bz2 .
tar xfj pack.tar.bz2

Jeśli okaże się, że $(find ...)jest za długi, aby zmienić format na,

find . -type f -name *.class | xargs tar cfj pack.tar.bz2

Wreszcie, skoro go trzymasz /usr/project/backup/, po co
zawracać sobie głowę ekstrakcją? Po prostu zachowaj tar.bz2, może z datą i znacznikiem czasu.

nik
źródło
To mi pomogło. Jestem w systemie Windows i walczę, próbując zainstalować rsynci sshzainstalować w systemie operacyjnym. Zamiast tego było to sprytne obejście. Dzięki!
rayryeng
2

Poniżej polecenie dla plików.

scp `find. -maxdepth 1 -name "* .log" \! -name "hs_err_pid2801.log" -type f` root @ IP: / tmp / test /

  1. IP będzie adresem IP serwera docelowego.
  2. -name „* .log” dla plików dołączanych.
  3. \! -name „hs_err_pid2801.log” dla plików wykluczeń.
  4. . obecnie działa reż.
  5. -type f dla typu pliku.

Poniżej polecenie dla katalogu.

scp -r `znajdź. -maxdepth 1 -name "lo *" \! -name "localhost" -type d` root @ IP: / tmp / test /

możesz dostosować powyższe polecenie zgodnie z wymaganiami.

Suneet Khurana
źródło
1

Po włączeniu uwierzytelniania opartego na kluczu ssh działałby następujący skrypt.

for x in `ssh user@remotehost 'find /usr/some -type f -name *.class'`; do y=$(echo $x|sed 's/.[^/]*$//'|sed "s/^\/usr//"); mkdir -p /usr/project/backup$y; scp $(echo 'user@remotehost:'$x) /usr/project/backup$y/; done
varun
źródło
1

Jeśli rzeczywiście chcesz używać scp, istnieje pośredni sposób. Powiedzmy, że chcemy skopiować cały plik .jpg z folderu lokalnego „/ src” do folderu „/ dst” na serwerze zdalnym 10.1.1.2:

#make a clean temp folder
mkdir /tmp/ttt
#copy all .jpg file and retain folder structure as-is
find /src -type f -name *.jpg -exec cp --parents \{\} /tmp/ttt \;
#copy to remote target folder as-is and retain original time attributes
scp -rp /tmp/ttt/* 10.1.1.2:/dst
#if copy ok, remove temp folder
rm -rf /tmp/ttt
Scott Chu
źródło
0
scp -i /home/<user>/.ssh/id_rsa -o "StrictHostKeyChecking=no" -rp /source/directory/path/[!.]* <target_user>@<target_system:/destination/directory/path
Vinay Babu
źródło
1
pomocne są również wyjaśnienia słowne wraz z kodem
con
-1
  1. Skopiuj folder źródłowy do somedir:

    cp -r srcdir somedir

  2. Usuń wszystkie niepotrzebne pliki:

    znajdź katalog -nazwa '.svn' -exec rm -rf {} \ +

  3. uruchom scp z somedir

dfa
źródło
skąd te wszystkie głosy przeciw tej odpowiedzi? Brzmi to jak bezpośrednie rozwiązanie tego pytania.
bcarroll
7
Ponieważ spowodowałoby to skopiowanie zbędnych plików, a następnie ich usunięcie, tracąc potencjalnie dużo czasu.
Oded
W przypadku programu, który przechodzi przez kilka etapów kompilacji, ma to sens. Może nastąpić tuż przed krokiem, który pakuje skompilowany kod do pliku tarlub zip-file. Zamiast tego nie ma kompresji (scp wykonuje kompresję), a „spakowany” kod jest kopiowany.
samvv
prawda, że ​​@samvv (wszystko zależy od konfiguracji, środowiska)
San Jay Falcon,
jeśli pliki są ignorowane z powodu ograniczeń przestrzennych, marnuje to miejsce i czas
jake