Bagaimana cara memfilter file saat menggunakan scp untuk menyalin dir secara rekursif?

99

Saya perlu menyalin semua file .class dari server ke lokal dengan semua dir yang dipesan. misal server:/usr/some/unknown/number/of/sub/folders/me.classakan jadi /usr/project/backup/some/unknown/number/of/sub/folders/me.classmasalah adalah, masih banyak file tidak berguna lainnya seperti file .svn-base yang tidak saya inginkan. bagaimana cara memfilternya jadi saya hanya scpfile kelas.?

derrdji
sumber
Saya suka opsi rsync yang disebutkan. Anda tidak menyebutkan apakah ini operasi satu kali, atau jika Anda akan mengotomatiskan ini berulang kali. Untuk operasi satu kali, penggunaan file find, grep -v, xargs, dan file sementara yang bijaksana akan mempersingkat pekerjaan ini.
pengguna47559

Jawaban:

152

Saya mungkin akan merekomendasikan menggunakan sesuatu seperti rsyncini karena includedan excludebenderanya, misalnya: -

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/

Beberapa tanda berguna lainnya:

  • -r untuk rekursif
  • -a untuk arsip (kebanyakan semua file)
  • -v untuk keluaran verbose
  • -e untuk menentukan ssh alih-alih default (yang seharusnya ssh, sebenarnya)
Gavin Gilmour
sumber
4
Pokoknya membuat ini mengabaikan subfolder yang tidak memiliki * file kelas di dalamnya? (yaitu saya tidak ingin banyak dirs kosong)
Grant Birchmeier
mengagumkan, dan ini juga cepat jahat!
Prasad Chalasani
2
Dapatkah Anda menjelaskan --include, bukan --include = Di halaman MAN, saya dapat menemukan penjelasan tentang --include = tetapi tidak
--include
1
Opsi -asudah termasuk -rsesuai dengan halaman manual rsync.
Georg Schölly
3
@GrantBirchmeier --prune-empty-dirsakan menghapus direktori kosong.
Elrond1337
74

Untuk mengecualikan dotfiles di direktori dasar:

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

[!.]* adalah shell glob yang meluas ke semua file di direktori kerja yang tidak dimulai dengan titik.

rgtk
sumber
10
Ini mungkin jawaban terbaik; menggunakan globs untuk memfilter file adalah cara yang harus dilakukan.
Yoshua Wuyts
1
Jika pilihan Anda terbatas pada scp seperti yang saya miliki, ini pasti membantu.
pengguna28095
3
Ini menunjukkan untuk mengecualikan file seperti yang diminta, tetapi bagaimana ini bisa dicapai untuk seluruh direktori?
Pille
37

Tidak ada fitur di scp untuk memfilter file. Untuk hal-hal "lanjutan" seperti ini, saya sarankan menggunakan rsync:

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

(baris ini menyalin rsync dari folder jauh ke folder saat ini)

Versi terbaru dari rsync tunnel melalui koneksi ssh secara otomatis secara default.

Ville Laurikari
sumber
10

Karena Anda bisa, scpAnda harusnya baik- baik saja ssh,
skrip yang berikut atau login dan jalankan ...

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

kembali (logout) ke server lokal dan 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

Jika Anda merasa $(find ...)terlalu lama untuk tar Anda berubah,

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

Akhirnya, karena Anda menyimpannya /usr/project/backup/,
mengapa repot-repot mengekstraksi? Simpan saja tar.bz2, mungkin dengan cap tanggal + waktu.

nik
sumber
Ini membantu saya. Saya menggunakan Windows dan saya berjuang untuk mencoba rsyncdan sshmenginstal di OS. Sebaliknya, ini adalah solusi yang cerdas. Terima kasih!
rayryeng
2

Di bawah perintah untuk file.

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

  1. IP akan menjadi alamat IP server tujuan.
  2. -name "* .log" untuk menyertakan file.
  3. \! -name "hs_err_pid2801.log" untuk mengecualikan file.
  4. . adalah dir kerja saat ini.
  5. -type f untuk tipe file.

Di bawah perintah untuk direktori.

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

Anda dapat menyesuaikan perintah di atas sesuai kebutuhan Anda.

Suneet Khurana
sumber
1

Dengan otentikasi berbasis kunci ssh diaktifkan, skrip berikut akan berfungsi.

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
sumber
1

Jika Anda memang ingin menggunakan scp, ada cara tidak langsung. Katakanlah kami ingin menyalin semua file .jpg di bawah folder lokal '/ src' ke folder '/ dst' di server jauh 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
sumber
0
scp -i /home/<user>/.ssh/id_rsa -o "StrictHostKeyChecking=no" -rp /source/directory/path/[!.]* <target_user>@<target_system:/destination/directory/path
Vinay Babu
sumber
1
penjelasan verbal juga membantu bersama dengan kode
con
-1
  1. Salin folder sumber Anda ke somedir:

    cp -r srcdir somedir

  2. Hapus semua file yang tidak dibutuhkan:

    temukan somedir -name '.svn' -exec rm -rf {} \ +

  3. luncurkan scp dari somedir

dfa
sumber
mengapa semua suara negatif pada jawaban ini? Ini terdengar seperti solusi via untuk pertanyaan tersebut.
bcarroll
7
Karena ini akan menyalin banyak file yang tidak perlu lalu menghapusnya, berpotensi membuang banyak waktu.
Oded
Untuk program yang melalui beberapa langkah kompilasi, ini sebenarnya sangat masuk akal. Ini bisa berjalan tepat sebelum langkah yang mengemas kode yang dikompilasi menjadi taratau zip-file. Sebaliknya, tidak ada kompresi (scp melakukan kompresi) dan kode 'paket' disalin.
samvv
benar bahwa @samvv (semua tergantung pada pengaturan, lingkungan)
San Jay Falcon
jika file diabaikan karena keterbatasan ruang, ini akan membuang-buang ruang dan juga waktu
jake