scp lub sftp kopiują wiele plików za pomocą jednego polecenia

313

Chciałbym skopiować pliki z / na zdalny serwer w różnych katalogach. Na przykład chcę uruchomić te 4 polecenia jednocześnie.

scp remote:A/1.txt local:A/1.txt
scp remote:A/2.txt local:A/2.txt
scp remote:B/1.txt local:B/1.txt
scp remote:C/1.txt local:C/1.txt

Jak najłatwiej to zrobić?

użytkownik987654
źródło
14
Kiedy tworzyłem skrypt, musiałem podać hasło do każdego polecenia. Czy mogę tego uniknąć?
user987654
11
Unikaj powtarzania hasła w ten sposób: zdalny scp: „A / 1.txt A / 2.txt B / 1.txt C / 1.txt” lokalny: ./
JohnMudd
stackoverflow.com/a/23748561/874188 (nominowany jako duplikat tego) ma fajną dodatkową technikę.
tripleee
2
Sugerowałbym, abyś rzucił okiem rsync, być może może ci pomóc w tej sprawie i wielu nadchodzących sprawach. Następnie, aby uniknąć wprowadzania hasła (nie mówiąc już wielokrotnie) należy przeczytać sshkluczy publicznych / prywatnych, np digitalocean.com/community/tutorials/how-to-set-up-ssh-keys--2
mnagel
1
Przykład na podstawie odpowiedzi @JohnMudd „s scp [email protected]:'/etc/openvpn/ca.crt /etc/openvpn/client/client0.crt /etc/openvpn/client/client0.key /etc/openvpn/client/ta.key' ./.
Eduardo Lucio

Odpowiedzi:

419

Skopiuj wiele plików ze zdalnego do lokalnego:

$ scp [email protected]:/some/remote/directory/\{a,b,c\} ./

Skopiuj wiele plików z lokalnego na zdalny:

$ scp foo.txt bar.txt [email protected]:~
$ scp {foo,bar}.txt [email protected]:~
$ scp *.txt [email protected]:~

Skopiuj wiele plików ze zdalnego do zdalnego:

$ scp [email protected]:/some/remote/directory/foobar.txt \
[email protected]:/some/remote/directory/

Źródło: http://www.hypexr.org/linux_scp_help.php

ios.id0
źródło
5
Pierwsze polecenie pominęło zakończenie „.”, A „{a, b, c}” jest równe \ {a, b, c \}.
duleshi
11
Myślę, że OP próbuje skopiować wiele plików z wielu folderów lokalnych do wielu folderów zdalnych, te przykłady nie wykonają zadania, ponieważ wszystkie będą scpować pliki do ~lub ./tylko.
aesede
20
Uwaga: nie ma spacji po przecinkach w nawiasach klamrowych. Właśnie spędziłem 10 minut, próbując dowiedzieć się, dlaczego moje polecenie nie działa, a to z powodu spacji.
deepak
13
@duleshi {a, b, c} nie jest dokładnie równe \ {a, b, c \} podczas kopiowania ze zdalnego na lokalny, ponieważ pierwszy wymaga hasła do każdego pliku, a drugi tylko raz.
Marcelo Ventura,
15
@MarceloVentura, @duleshi: Chciałbym również dodać, że użycie \{a,b,c\}spowoduje przeniesienie plików w jednym połączeniu / partii (ponieważ zostaną one rozwinięte na zdalnym hoście), podczas gdy użycie {a,b,c}spowoduje otwarcie wielu połączeń, a narzut jest dość zauważalne przy przesyłaniu wielu plików
omninonsense 9.04.16
140

Z lokalnego na serwer:

scp file1.txt file2.sh [email protected]:~/pathtoupload

Z serwera na lokalny:

scp -T [email protected]:"file1.txt file2.txt" "~/yourpathtocopy"

Gtr_py
źródło
6
To powinna być odpowiedź na górze, ponieważ serwer nie pyta o hasło do każdego pliku :)
motagirl2 30.01.2019
Nie działa na kliencie na Ubuntu 18 (zsh). Nie jestem pewien, gdzie to powinno działać. `` (venv) ➜ git: (master) ✗ scp root @ 172.29..xxx.yyy: "/ usr / local / bin / kubectl /root/.kube/config" / tmp / root @ 172.29..xxx. hasło yyy: błąd protokołu: nazwa pliku nie zgadza się z żądaniem ``
jseguillon 26.0419
3
@ motagirl2 Najlepsza odpowiedź nie wymaga podania hasła do każdego pliku, o ile unikasz nawiasów klamrowych odwrotnym ukośnikiem. Ta odpowiedź powoduje błąd, że nie można znaleźć pliku.
Pluto,
1
@jseguillon Dodaj -Topcję, aby ukryć ten błąd.
Przywróć Monikę
1
drugi działa na moich komputerach, ale tylko bez opcji -T
Richard DiSalvo,
71

Możesz kopiować całe katalogi za pomocą -rprzełącznika, więc jeśli możesz wyizolować swoje pliki do własnego katalogu, możesz skopiować wszystko naraz.

scp -r ./dir-with-files user@remote-server:upload-path

scp -r user@remote-server:path-to-dir-with-files download-path

więc na przykład

scp -r [email protected]:/var/log ~/backup-logs

Lub jeśli jest ich tylko kilka, możesz użyć:

scp 1.txt 2.txt 3.log user@remote-server:upload-path
Jiri Kremser
źródło
Czy to działa, jeśli moim miejscem docelowym jest root, a ja robię katalog etc, na przykład: scp -r / backups / etc root @ linuxbox: / gdzie moje źródło jest bardzo rzadkim katalogiem z takimi rzeczami jak „hosts” i nginx / sites -dostępne itp?
Tomachi,
47

Jak wspomniał Jiri, możesz użyć scp -r user@host:/some/remote/path /some/local/path do kopiowania plików rekurencyjnie. Zakłada się, że istnieje jeden katalog zawierający wszystkie pliki, które chcesz przenieść (i nic więcej).

Jednak SFTP stanowi alternatywę, jeśli chcesz przesyłać pliki z wielu różnych katalogów, a miejsca docelowe nie są identyczne:

sftp user@host << EOF
  get /some/remote/path1/file1 /some/local/path1/file1
  get /some/remote/path2/file2 /some/local/path2/file2
  get /some/remote/path3/file3 /some/local/path3/file3
EOF

Używa składni „tutaj doc” do definiowania sekwencji poleceń wejściowych SFTP. Alternatywnie, możesz umieścić polecenia SFTP w pliku tekstowym i wykonaćsftp user@host -b batchFile.txt

alev
źródło
3
To jedyna odpowiedź, która faktycznie odpowiada na pytanie. Dzięki. scpZbyt długo analizowałem instrukcję, próbując znaleźć tę funkcję, i chyba scp jej nie ma.
sudo
1
To wydaje się być najlepszą, najbardziej elastyczną odpowiedzią. Uwaga: Potknąłem się, dopóki nie zdałem sobie sprawy, że muszę użyć pełnej ścieżki jak /home/vagrant/Code/zamiast ~/Code/.
Ryan
To najlepsza odpowiedź, tylko nie zapomnij dodać - rdo katalogów
Chris_Rands
25

Odpowiedzi z {file1,file2,file3} działa tylko z bash (zdalnie lub lokalnie)

Prawdziwy sposób to:

scp user@remote:'/path1/file1 /path2/file2 /path3/file3' /localPath
Vouze
źródło
1
Fantastyczny! Czasami używam powłok nieobsługujących bashów, a to niezmiernie pomaga. Nie tylko prawdziwy sposób, ale właściwy sposób.
Paul B.
1
Globbing z {…, …, …}działaniem w wielu powłokach, nie tylko w Bash. Jednak działa to w dowolnej powłoce, więc jest wyraźnie lepsze.
Piotr Dobrogost
Potrzebuje więcej cytatów. Te ścieżki mogą zawierać spacje.
Amit Naidu
1
No to jedziemy! Głosowałbym za tym wiele razy, ale mogę to zrobić tylko raz! Dziękuję Vouze!
André Pacheco,
17

Po dłuższej zabawie ze scp znalazłem najsolidniejsze rozwiązanie:

(Uwaga na pojedyncze i podwójne znaki cudzysłowu)

Lokalny do zdalnego:

scp -r "FILE1" "FILE2" HOST:'"DIR"'

Zdalne do lokalnego:

scp -r HOST:'"FILE1" "FILE2"' "DIR"

Zauważ, że cokolwiek po „HOST:” zostanie wysłane do pilota i tam parsowane. Musimy więc upewnić się, że nie są one przetwarzane przez lokalną powłokę. Właśnie dlatego pojawiają się pojedyncze cudzysłowy. Podwójne cudzysłowy są używane do obsługi spacji w nazwach plików.

Jeśli wszystkie pliki znajdują się w tym samym katalogu, możemy użyć *, aby dopasować je wszystkie, np

scp -r "DIR_IN"/*.txt HOST:'"DIR"'
scp -r HOST:'"DIR_IN"/*.txt' "DIR"

W porównaniu do użycia składni „{}”, która jest obsługiwana tylko przez niektóre powłoki, ta jest uniwersalna

eosphorox
źródło
Dziękujemy za pomoc ze spacjami w nazwach plików. Korzystałem z {}, więc po cytowaniu musiałem też uciec.
Noumenon
3
W przypadku, gdy chcesz użyć znaku tyldy (~) w swoim katalogu domowym w ścieżkach. Zauważ, że ~ i / muszą znajdować się poza cudzysłowami. `` `scp -r [email protected]: '~ /" bin / set-vpn-kill-switch "~ /" bin / flush-iptables "' ~ /" "` `
Rob Waa
{}Składnia ułatwia kopiowanie wielu plików w tym samym katalogu, czy jest jakiś sposób aby to zrobić z scp -rtak że "FILE1" "FILE2"mogą być ścieżki względne i bezwzględne ścieżki nie do plików?
dtasev
15

Najprostszy sposób to

local$ scp remote:{A/1,A/2,B/3,C/4}.txt ./

Tak więc lista {..} może zawierać katalogi (A, B i C tutaj są katalogami; „1.txt” i „2.txt” to nazwy plików w tych katalogach).

Chociaż skopiuje wszystkie cztery pliki do jednego katalogu lokalnego - nie jestem pewien, czy tego właśnie chciałeś.

W powyższym przypadku skończysz na plikach zdalnych A / 1.txt, A / 2.txt, B / 3.txt i C / 4.txt skopiowanych do jednego lokalnego katalogu o nazwach plików ./1.txt, ./2.txt, ./3.txt i ./4.txt

Tagar
źródło
Czy nie zastąpiłoby to zawartości A / 1.txt zawartością B / 1.txt na komputerze lokalnym?
Yves Dorfsman,
dobra uwaga… poprawiony przykład (więc teraz nie nadpisze) i dodany opis. Dzięki.
Tagar
Takie rozszerzenia nawiasów klamrowych są funkcją Bash i nie można ich przenosić np sh. Na POSIX .
tripleee
1
@tripleee, dzięki. to może nie być posiks, ale działa nie tylko w bash. Cały czas używam ksh i tam też działa.
Tagar
1
Możesz także mieszać katalogi i pliki, wykonując:local$ scp -r remote:{A/1.txt,A/2.txt,B/3.txt,C/4.txt,D,F} ./
donhector,
13

Problem : Kopiowanie wielu katalogów ze zdalnego serwera na komputer lokalny za pomocą pojedynczego polecenia SCP i zachowanie każdego katalogu tak, jak jest na zdalnym serwerze.

Rozwiązanie : SCP może to zrobić z łatwością. Rozwiązuje to irytujący problem wielokrotnego wprowadzania hasła podczas korzystania z SCP z wieloma folderami. W rezultacie oszczędza to również dużo czasu!

na przykład

# copies folders t1, t2, t3 from `test` to your local working directory
# note that there shouldn't be any space in between the folder names;
# we also escape the braces.
# please note the dot at the end of the SCP command

~$ cd ~/working/directory
~$ scp -r [email protected]:/work/datasets/images/test/\{t1,t2,t3\}  .

PS: Motywowany tą świetną odpowiedzią: scp lub sftp kopiują wiele plików za pomocą jednego polecenia


W oparciu o komentarze działa to również dobrze w Git Bash w systemie Windows

kmario23
źródło
3
PS nie dodają spacji między przedmiotami. tzn. \ {t1, t2, t3 \} ------> Zmarnowałem tutaj dziesięć minut ... lol
kenberkeley,
1
To najlepsza odpowiedź, ponieważ kiedy wyjdziesz z nawiasów klamrowych, zostanie to zinterpretowane jako pojedyncze polecenie i nie będzie
wymagało podania
@ Amaynut tak, dokładnie! To z pewnością oszczędza dużo czasu i wysiłku :)
kmario23
12

Skopiuj wiele katalogów:

scp -r dir1 dir2 dir3 [email protected]:~/
Yuliskov
źródło
pytanie brzmiało, jak skopiować ze zdalnego katalogu do lokalnego, a nie odwrotnie.
Tagar
5

Możesz to zrobić w następujący sposób:

scp hostname@serverNameOrServerIp:/path/to/files/\\{file1,file2,file3\\}.fileExtension ./

Spowoduje to pobranie wszystkich wymienionych nazw plików do dowolnego lokalnego katalogu.

Pamiętaj, aby nie wstawiać spacji między każdą nazwą pliku, tylko przecinek ,.

J_rad
źródło
1
Jest to dobre, gdy rozszerzenie jest takie samo. Można to zapisać tak, /path/to/files/\\{file1.ext,file2.ext,file3.ext\\}jakby pliki miały różne rozszerzenia. Uwaga dla osób PowerShell (teraz, gdy MS dołączyło do drużyny), musisz użyć `zamiast tego ucieczki:/path/to/files/`{file1.ext,file2.ext,file3.ext`}
dtasev
3

UWAGA: Z góry przepraszam za odpowiedź tylko na część powyższego pytania. Uważam jednak, że te polecenia są przydatne w moich bieżących potrzebach dotyczących Uniksa.

Przesyłanie określonych plików z komputera lokalnego na komputer zdalny:

~/Desktop/dump_files$ scp file1.txt file2.txt lab1.cpp etc.ext [email protected]:Folder1/DestinationFolderForFiles/

Przesyłanie całego katalogu z komputera lokalnego na komputer zdalny:

~$ scp -r Desktop/dump_files [email protected]:Folder1/DestinationFolderForFiles/

Pobieranie całego katalogu ze zdalnego komputera na komputer lokalny:

~/Desktop$ scp -r [email protected]:Public/web/ Desktop/

fat43r 80ard
źródło
3

W moim przypadku jestem ograniczony tylko do używania polecenia sftp.
Musiałem więc użyć pliku wsadowego z sftp. Utworzyłem skrypt taki jak poniżej. Zakłada się, że pracujesz w katalogu / tmp i chcesz umieścić pliki w systemie destdir_on_remote_system w systemie zdalnym. Działa to również tylko przy nieinteraktywnym logowaniu. Musisz skonfigurować klucze publiczne / prywatne, abyś mógł się zalogować bez podawania hasła. Zmień w razie potrzeby.

#!/bin/bash

cd /tmp
# start script with list of files to transfer
ls -1 fileset1* > batchfile1
ls -1 fileset2* >> batchfile1

sed -i -e 's/^/put /' batchfile1
echo "cd destdir_on_remote_system" > batchfile
cat batchfile1 >> batchfile
rm batchfile1

sftp -b batchfile user@host
dminear
źródło
2

twoje polecenie działa idealnie, ale chcę również zmienić nazwę pliku podczas wysyłania lokalnego do zdalnego. Napisałem polecenie: - sshpass -p hasło scp /path/to/file.txt root @ nazwa_hosta: /path/newfile.txt

Daje jednak błąd, że /path/newfile.txt: Nie znaleziono takiego pliku lub katalogu plz pomaga mi w tej sytuacji

Reshmi KC
źródło
Upewnij się, że zdalny katalog hostname:/path/faktycznie istnieje i jest dostępny.
Amit Naidu
1

scp używa ssh do przesyłania danych z tym samym uwierzytelnieniem i zapewnia takie samo bezpieczeństwo jak ssh.

Najlepszą praktyką jest wdrożenie „KLUCZY SSH I AUTORYZACJI KLUCZA PUBLICZNEGO”. Dzięki temu możesz pisać swoje skrypty, nie martwiąc się o uwierzytelnianie. Proste.

Zobacz CO TO JEST SSH-KEYGEN

augusto
źródło
1

W konkretnym przypadku, w którym wszystkie pliki mają to samo rozszerzenie, ale z innym sufiksem (powiedzmy numer pliku dziennika), stosujesz:

scp [email protected]:/some/log/folder/some_log_file.* ./

Spowoduje to skopiowanie wszystkich plików o nazwie plik_logu z podanego folderu w zdalnym folderze, tj. Plik_logu.1, plik_logu.2, plik_logu.3.

Guy Avraham
źródło
-1
scp remote:"[A-C]/[12].txt" local:
unxnut
źródło
dzięki, ale to tylko przykład, a rzeczywista nazwa pliku lub katalogu jest bardziej złożona. Ale mam ich listę.
user987654
Czy możesz je opisać wyrażeniem regularnym?
unxnut
Czy można zachować tę samą strukturę katalogów w katalogu docelowym za pomocą wyrażeń regularnych?
user987654
1
Tak, powinieneś być w stanie to zrobić z -ropcją scp. I możesz zachować inne atrybuty (np. Znacznik czasu) z -popcją.
unxnut