ubuntuusers.de

Dateien von einem Server kopieren

Status: Ungelöst | Ubuntu-Version: Ubuntu MATE 16.04 (Xenial Xerus)
Antworten |

Blitz8917

Anmeldungsdatum:
8. September 2017

Beiträge: Zähle...

Hallo Ubuntu-User,

ich bin noch ein neuling auf dem Gebiet Shell Programmierung.

Ich habe folgende Frage: ich habe eine Textdatei wo ich 9 Zeilen stehen habe. Die Zeilen enthalten jeweils einen direkten Pfad zu einem Dokument. Diese Dateien möchte ich gerne von einem Server per scp auf meinen Rechner kopieren. Dazu soll aus der Datei ausgelesen werden. So das man die Pfade nicht extra eingeben muss.

Grüße Blitz

seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 11269

Wohnort: München

Hallo, meinst du sowas?

readarray -t server_files < myfiles.txt
scp user@host:{$(printf "%s," "${server_files[@]}")} /path/to/target_dir/ 

Blitz8917

(Themenstarter)

Anmeldungsdatum:
8. September 2017

Beiträge: 2

Ich danke dir für die Schnelle Lösung, habe aber schon was anderes funktionierendes gefunden. 😉

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13219

Blitz8917 schrieb:

Ich danke dir für die Schnelle Lösung, habe aber schon was anderes funktionierendes gefunden. 😉

Dann verrate uns doch, was Du gefunden hast, damit andere auch profitieren können.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13219

seahawk1986 schrieb:

Hallo, meinst du sowas?

readarray -t server_files < myfiles.txt
scp user@host:{$(printf "%s," "${server_files[@]}")} /path/to/target_dir/ 

Bist Du sicher, dass das funktioniert?

1
2
3
$ server_files=(foo bar)
$ echo scp user@host:{$(printf "%s," "${server_files[@]}")} /path/to/target_dir/
scp user@host:{foo,bar,} /path/to/target_dir/

Mir wäre neu, dass scp so eine Konstruktion mit geschweiften Klammern versteht. Vielleicht hattest Du eher etwas mit eval im Sinn um die Brace-Expansion zu nutzen. Aber da würde sich paste eher anbieten, weil man sich dann kein Komma am Ende einfängt.

Ich hätte ja eher an so etwas gedacht:

1
xargs -r -a myfiles.txt -I {} echo scp user@host:{} /path/to/target_dir/

Wobei das eklig wird, wenn man immer wieder das Passwort eingeben muss. Dann wäre vielleicht eher so etwas angesagt:

1
scp $(sed 's#^#user@host:#' myfiles.txt) /path/to/target_dir/

seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 11269

Wohnort: München

rklm schrieb:

seahawk1986 schrieb:

readarray -t server_files < myfiles.txt
scp user@host:{$(printf "%s," "${server_files[@]}")} /path/to/target_dir/ 

Bist Du sicher, dass das funktioniert?

Ja (man sollte aber noch einfache Anführungszeichen um die String-Ersetzung bei printf setzen: "'%s',", damit er nicht über Kommata im Pfad stolpert) - wenn man sich die verbose-Ausgabe von scp anzeigen lässt, sieht man was da passiert:

$ cat myfiles.txt 
/tmp/foo1.txt
/tmp/foo2.txt
/tmp/foo3.txt
/tmp/foo4.txt
/tmp/foo,bar.txt
$ readarray -t foo < myfiles.txt 
$ scp -v user@host:{$(printf "'%s'," "${foo[@]}")} ./
Executing: program /usr/bin/ssh host host, user user, command scp -v -f {'/tmp/foo1.txt','/tmp/foo2.txt','/tmp/foo3.txt','/tmp/foo4.txt','/tmp/foo,bar.txt',}
OpenSSH_7.5p1, OpenSSL 1.1.0f  25 May 2017
[...]
debug1: Authentication succeeded (password).
Authenticated to host ([192.168.1.173]:22).
debug1: channel 0: new [client-session]
debug1: Requesting no-more-sessions@openssh.com
debug1: Entering interactive session.
debug1: pledge: network
debug1: client_input_global_request: rtype hostkeys-00@openssh.com want_reply 0
debug1: Sending command: scp -v -f {'/tmp/foo1.txt','/tmp/foo2.txt','/tmp/foo3.txt','/tmp/foo4.txt','/tmp/foo,bar.txt',}
Sending file modes: C0644 2 foo1.txt
Sink: C0644 2 foo1.txt
foo1.txt                                                                                     100%    2     1.1KB/s   00:00    
Sending file modes: C0644 2 foo2.txt
Sink: C0644 2 foo2.txt
foo2.txt                                                                                     100%    2     1.6KB/s   00:00    
Sending file modes: C0644 2 foo3.txt
Sink: C0644 2 foo3.txt
foo3.txt                                                                                     100%    2     0.0KB/s   00:00    
Sending file modes: C0644 2 foo4.txt
Sink: C0644 2 foo4.txt
foo4.txt                                                                                     100%    2     0.8KB/s   00:00    
Sending file modes: C0644 0 foo,bar.txt
Sink: C0644 0 foo,bar.txt
foo,bar.txt                                                                                  100%    0     0.0KB/s   00:00    
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
debug1: client_input_channel_req: channel 0 rtype eow@openssh.com reply 0
debug1: channel 0: free: client-session, nchannels 1
debug1: fd 0 clearing O_NONBLOCK
debug1: fd 1 clearing O_NONBLOCK
Transferred: sent 2744, received 3372 bytes, in 0.2 seconds
Bytes per second: sent 12636.6, received 15528.6
debug1: Exit status 0 

Der Ausdruck für den Pfad wird nach meinem Verständnis erst auf den Server evaluiert (die Shell dort muss das natürlich können), man darf ja z.B. auch Wildcards in den Dateinamen nutzen:

$ scp 'user@host:/tmp/foo*' .
foo,bar.txt                                   100%    0     0.0KB/s   00:00    
foo1.txt                                      100%    2     0.1KB/s   00:00    
foo2.txt                                      100%    2     1.1KB/s   00:00    
foo3.txt                                      100%    2     0.9KB/s   00:00    
foo4.txt                                      100%    2     1.1KB/s   00:00 

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13219

seahawk1986 schrieb:

rklm schrieb:

Bist Du sicher, dass das funktioniert?

Ja (solange es keine Kommata in den Pfaden gibt) - der Pfad wird ja erst auf den Host evaluiert, man kann ja z.B. auch Wildcards in den Dateinamen nutzen.

Ah, cool! Ich würde dann aber trotzdem paste nutzen und die erste Zeile sparen, also:

1
scp user@host:{$(paste -sd , server_files)} /path/to/target_dir/ 

Wenn man sich die verbose-Ausgabe von scp anzeigen lässt, sieht man was da passiert:

Danke für die Fortbildung! 👍

Thomas_Do Team-Icon

Moderator
Avatar von Thomas_Do

Anmeldungsdatum:
24. November 2009

Beiträge: 8808

Blitz8917 schrieb:

Ich danke dir für die Schnelle Lösung, habe aber schon was anderes funktionierendes gefunden. 😉

Ich fände ich es gut, wenn man vor einer Frage hier, erst einmal ausführlich selbst nach einer Lösung suchen würde. Zwischen Frage und Anwort lagen nur 35 min! So schnell ist kein kostenpflichtiger Service 😉. Ist schade, um die "verschwendete" Zeit der Helfer. Ist mir auch schon öfter passiert. In diesem Fall hilft die Antwort aber sicher auch einigen anderen weiter.

Danke seahawk1986

Antworten |