Làm thế nào để lọc các tệp khi sử dụng scp để sao chép dir một cách đệ quy?


99

Tôi cần sao chép tất cả các tệp .class từ máy chủ sang cục bộ với tất cả dir được bảo lưu. ví dụ như server:/usr/some/unknown/number/of/sub/folders/me.classsẽ là /usr/project/backup/some/unknown/number/of/sub/folders/me.classvấn đề là, có rất nhiều file vô dụng khác như tập tin svn-base mà tôi không muốn. làm cách nào để lọc chúng để tôi chỉ có scpcác tệp .class?


Tôi thích tùy chọn rsync được đề cập. Bạn đã không đề cập đến việc đây là hoạt động một lần hay bạn sẽ tự động hóa việc này nhiều lần. Đối với hoạt động một lần, việc sử dụng hợp lý các tệp tìm kiếm, grep -v, xargs và các tệp tạm thời sẽ giúp thực hiện điều này một cách ngắn gọn.
user47559

Câu trả lời:


152

Tôi có lẽ khuyên bạn nên sử dụng một cái gì đó như thế rsyncnày vì nó includeexcludecờ, ví dụ: -

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/

Một số cờ hữu ích khác:

  • -r cho đệ quy
  • -a để lưu trữ (hầu hết là tất cả các tệp)
  • -v cho đầu ra dài dòng
  • -e để chỉ định ssh thay vì mặc định (thực tế phải là ssh)

4
Dù sao để làm cho điều này bỏ qua các thư mục con không có tệp * lớp trong chúng? (ví dụ: Tôi không muốn có một loạt các dirs trống)
Grant Birchmeier

tuyệt vời, và điều này cũng nhanh chóng xấu xa!
Prasad Chalasani

2
Bạn có thể giải thích --bao gồm, không --bao gồm = Trong các trang MAN, tôi có thể tìm lời giải thích trên --bao gồm = nhưng không --bao gồm
bazz

1
Tùy chọn -ađã bao gồm -rtheo các trang người đàn ông rsync.
Georg Schölly

3
@GrantBirchmeier --prune-empty-dirssẽ xóa các dirs trống.
Elrond1337

74

Để loại trừ các tệp dotfiles trong thư mục cơ sở:

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

[!.]* là một khối cầu mở rộng cho tất cả các tệp trong thư mục làm việc không bắt đầu bằng dấu chấm.


10
Đây có lẽ là câu trả lời tốt nhất; cách sử dụng quả địa cầu để lọc tệp là cách tốt nhất.
Yoshua Wuyts

1
Nếu tùy chọn của bạn bị hạn chế trong phạm vi scp như tôi đã có, điều này chắc chắn đã hữu ích.
user28095 12/12/15

3
Điều này cho biết để loại trừ các tệp như được hỏi, nhưng làm thế nào có thể đạt được điều này cho toàn bộ thư mục?
Pille

37

Không có tính năng nào trong scp để lọc tệp. Đối với những thứ "nâng cao" như thế này, tôi khuyên bạn nên sử dụng rsync:

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

(dòng này sao chép rsync từ thư mục xa sang thư mục hiện tại)

Các phiên bản gần đây của đường hầm rsync qua kết nối ssh tự động theo mặc định.


10

Vì bạn có thể scpnên bạn có thể chấp nhận ssh,
hoặc tập lệnh sau hoặc đăng nhập và thực thi ...

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

quay lại (đăng xuất) về máy chủ cục bộ và 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

Nếu bạn thấy $(find ...)khoảng thời gian quá dài để thay đổi tar thành,

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

Cuối cùng, vì bạn đang giữ nó /usr/project/backup/,
tại sao phải trích xuất? Chỉ cần giữ lại tar.bz2, có thể có dấu ngày + giờ.


Điều này đã giúp tôi. Tôi đang sử dụng Windows và tôi đang cố gắng tải rsyncsshcài đặt hệ điều hành này. Thay vào đó, đây là một cách giải quyết thông minh. Cảm ơn!
rayryeng

2

Lệnh dưới đây cho các tệp.

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

  1. IP sẽ là địa chỉ IP của máy chủ đích.
  2. -name "* .log" cho các tệp bao gồm.
  3. \! -name "hs_err_pid2801.log" để loại trừ tệp.
  4. . hiện đang làm việc dir.
  5. -type f cho loại tệp.

Lệnh dưới đây cho thư mục.

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

bạn có thể tùy chỉnh lệnh trên theo yêu cầu của bạn.


1

Với xác thực dựa trên khóa ssh được bật, tập lệnh sau sẽ hoạt động.

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

1

Nếu bạn thực sự muốn sử dụng scp, có một cách gián tiếp. Nói chúng tôi muốn sao chép tất cả tệp .jpg trong thư mục cục bộ '/ src' vào thư mục '/ dst' trong máy chủ từ xa 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

0
scp -i /home/<user>/.ssh/id_rsa -o "StrictHostKeyChecking=no" -rp /source/directory/path/[!.]* <target_user>@<target_system:/destination/directory/path

1
giải thích bằng lời nói cũng hữu ích cùng với mã
con

-1
  1. Sao chép thư mục nguồn của bạn vào somedir:

    cp -r srcdir somedir

  2. Xóa tất cả các tệp không cần thiết:

    tìm somedir -name '.svn' -exec rm -rf {} \ +

  3. khởi chạy scp từ somedir


tại sao tất cả các phiếu phản đối cho câu trả lời này? Điều này có vẻ giống như một giải pháp thông qua cho câu hỏi.
xe tải vào

7
Bởi vì điều này sẽ sao chép một loạt các tệp không cần thiết sau đó xóa chúng, lãng phí rất nhiều thời gian.
Oded

Đối với một chương trình trải qua một số bước biên dịch, điều này thực sự có ý nghĩa. Nó có thể đi ngay trước bước đóng gói mã đã biên dịch thành một tarhoặc zip-tệp. Thay vào đó, không có nén (scp thực hiện nén) và mã 'đóng gói' được sao chép qua.
samvv

đúng là @samvv (tất cả phụ thuộc vào việc thiết lập, môi trường)
San Jay Falcon

nếu tệp đang bị bỏ qua vì hạn chế về không gian, điều này sẽ lãng phí không gian cũng như thời gian
jake
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.