scp 或 sftp 使用单个命令复制多个文件

Posted

技术标签:

【中文标题】scp 或 sftp 使用单个命令复制多个文件【英文标题】:scp or sftp copy multiple files with single command 【发布时间】:2013-05-28 23:32:01 【问题描述】:

我想将文件从/复制到不同目录中的远程服务器。 例如,我想一次运行这 4 个命令。

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

最简单的方法是什么?

【问题讨论】:

当我编写脚本时,我必须为每个命令输入密码。我可以避免吗? 避免这样重复密码:scp remote:"A/1.txt A/2.txt B/1.txt C/1.txt" local:./ ***.com/a/23748561/874188(被提名为这个的副本)有一个很好的附加技术。 我建议你看看rsync,也许它可以在这种情况下和许多即将发生的情况下帮助你。然后,为避免输入密码(更不用说多次),您应该阅读有关 ssh 公钥/私钥的信息,例如digitalocean.com/community/tutorials/how-to-set-up-ssh-keys--2 示例基于@JohnMudd 的回答:scp root@192.168.56.120:'/etc/open***/ca.crt /etc/open***/client/client0.crt /etc/open***/client/client0.key /etc/open***/client/ta.key' ./ 【参考方案1】:

从远程复制多个文件到本地:

$ scp your_username@remote.edu:/some/remote/directory/\a,b,c\ ./

从本地复制多个文件到远程:

$ scp foo.txt bar.txt your_username@remotehost.edu:~
$ scp foo,bar.txt your_username@remotehost.edu:~
$ scp *.txt your_username@remotehost.edu:~

将多个文件从远程复制到远程:

$ scp your_username@remote1.edu:/some/remote/directory/foobar.txt \
your_username@remote2.edu:/some/remote/directory/

来源:http://www.hypexr.org/linux_scp_help.php

【讨论】:

第一个命令省略了结尾“.”,'a,b,c' 等于 \a,b,c\。 我认为 OP 正在尝试将多个本地文件夹中的多个文件复制到多个远程文件夹,这些示例将无法完成这项工作,因为它们都只会将文件 scp 到 ~./ . 注意:花括号内的逗号后没有空格。我只花了 10 分钟试图弄清楚为什么我的命令不起作用,这是因为空格。 @duleshi a,b,c 不完全等于 \a,b,c\ 从远程复制到本地时,因为第一个需要每个文件的密码,而第二个需要密码只有一次。 @MarceloVentura, @duleshi:另外,我想补充一点,使用\a,b,c\ 将在单个连接/批处理中传输文件(因为它们将在远程主机上扩展),而使用a,b,c会打开多个连接,传输大量文件时开销非常明显【参考方案2】:

从本地到服务器:

scp file1.txt file2.sh username@ip.of.server.copyto:~/pathtoupload

从服务器到本地:

scp -T username@ip.of.server.copyfrom:"file1.txt file2.txt" "~/yourpathtocopy"

【讨论】:

这应该是最上面的答案,因为服务器不会要求每个文件的密码:) 无法在 Ubuntu 18 (zsh) 上的客户端上运行。不知道这应该在哪里工作。 ``` (venv) ➜ git:(master) ✗ scp root@172.29..xxx.yyy:"/usr/local/bin/kubectl /root/.kube/config" /tmp/ root@172.29..xxx. yyy 的密码:协议错误:文件名与请求不匹配``` @motagirl2 只要您用反斜杠转义大括号,最佳答案就不会要求每个文件的密码。这个答案给了我一个找不到文件的错误。 @jseguillon 添加-T 选项以抑制该错误。 第二个可以在我的机器上运行,但没有 -T 选项【参考方案3】:

您可以使用-r 开关复制整个目录,因此如果您可以将文件隔离到自己的目录中,则可以一次复制所有内容。

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

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

比如

scp -r root@192.168.1.100:/var/log ~/backup-logs

或者如果只有几个,你可以使用:

scp 1.txt 2.txt 3.log user@remote-server:upload-path

【讨论】:

如果我的目标是 root 并且我正在执行 etc 目录,例如:scp -r /backups/etc root@linuxbox:/ 我的源是一个非常稀疏的目录,这是否有效比如“主机”和 nginx/sites-available 等?【参考方案4】:

正如 Jiri 提到的,您可以使用 scp -r user@host:/some/remote/path /some/local/path 递归地复制文件。这假设有一个目录包含您要传输的所有文件(仅此而已)。

但是,如果您想从多个不同的目录传输文件,并且目的地不相同,SFTP 提供了一种替代方案:

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

这使用"here doc" 语法来定义一系列SFTP 输入命令。作为替代方案,您可以将 SFTP 命令放入文本文件并执行 sftp user@host -b batchFile.txt

【讨论】:

这是唯一真正回答问题的答案。谢谢。我一直在谷歌搜索和分析 scp 手册太久试图找到这个功能,我猜 scp 没有它。 这似乎是最好、最灵活的答案。注意:我被绊倒了,直到我意识到我需要使用像 /home/vagrant/Code/ 这样的完整路径而不是 ~/Code/ 这是最好的答案,只是不要忘记为目录添加- r【参考方案5】:

file1,file2,file3 的答案仅适用于 bash(远程或本地)

真正的方法是:

scp user@remote:'/path1/file1 /path2/file2 /path3/file3' /localPath

【讨论】:

太棒了!我有时会使用非 bash shell,这非常有帮助。不仅是真正的方式,而且是正确的方式。 使用…, …, … 进行通配可以在许多shell 中使用,不仅在Bash 中。然而,这适用于任何外壳,所以显然更好。 需要更多引用。这些路径可以包含空格。 好了!我会多次投票,但我只能投一次!谢谢你!【参考方案6】:

在玩了一段时间 scp 之后,我找到了最强大的解决方案:

(注意单引号和双引号)

本地到远程:

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

远程到本地:

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

请注意,“HOST:”之后的任何内容都将被发送到远程并在那里解析。所以我们必须确保它们不被本地shell处理。这就是单引号出现的原因。双引号用于处理文件名中的空格。

如果文件都在同一个目录下,我们可以用*来匹配,比如

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

相对于只有部分shell支持的“”语法,这个是通用的

【讨论】:

感谢您帮助解决文件名中的空格问题。我使用的是 方法,所以我还必须在引用后用 \ 转义它们。 如果您想在路径中使用波浪字符 (~) 作为主目录。注意 ~ 和 / 必须在引号之外。 ``` scp -r robwaa@192.168.1.101:'~/"bin/set-***-kill-switch" ~/"bin/flush-iptables"' ~/"" `` 语法使得从同一个目录复制多个文件更容易,有没有办法用scp -r 做到这一点,以便"FILE1" "FILE2" 可以是相对路径而不是绝对路径文件?【参考方案7】:

最简单的方法是

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

所以 .. 列表可以包含目录(这里的 A、B 和 C 是目录;“1.txt”和“2.txt”是这些目录中的文件名)。

虽然它会将所有这四个文件复制到一个本地目录中 - 不确定这是否是您想要的。

在上述情况下,您最终会将远程文件 A/1.txt、A/2.txt、B/3.txt 和 C/4.txt 复制到单个本地目录,文件名为 ./1 .txt、./2.txt、./3.txt 和 ./4.txt

【讨论】:

这不会用本地机器上的B/1.txt的内容覆盖A/1.txt的内容吗? 好点.. 调整示例(所以现在它不会覆盖)并添加描述。谢谢。 像这样的大括号扩展是 Bash 功能,不能移植到例如POSIX sh. @tripleee,谢谢。它可能不是 posix,但它不仅适用于 bash。我一直在使用 ksh,它也可以在那里工作。 你也可以混合目录和文件:local$ scp -r remote:A/1.txt,A/2.txt,B/3.txt,C/4.txt,D,F ./【参考方案8】:

问题:使用单个 SCP 命令将多个目录从远程服务器复制到本地计算机,并在远程服务器中保留每个目录。

解决方案:SCP 可以轻松做到这一点。这解决了在多个文件夹中使用 SCP 时多次输入密码的烦人问题。因此,这也节省了大量时间!

例如

# 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 username@contact.server.de:/work/datasets/images/test/\t1,t2,t3\  .

PS:被这个好答案激励:scp or sftp copy multiple files with single command


基于 cmets,这在 Windows 上的 Git Bash

中也可以正常工作

【讨论】:

P.S.不要在项目之间添加空格。即 \t1, t2, t3\ ------> 我在这里浪费了十分钟...lol 这是最好的答案,因为当您转义大括号时,它将被解释为单个命令,并且不会要求每次传输的密码 @Amaynut 是的,完全正确!这当然可以节省大量时间和精力:)【参考方案9】:

复制多个目录:

scp -r dir1 dir2 dir3 admin@127.0.0.1:~/

【讨论】:

问题是如何从远程目录复制到本地目录,而不是其他方式。【参考方案10】:

你可以这样做:

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

这会将所有列出的文件名下载到您所在的任何本地目录。

确保不要在每个文件名之间放置空格,仅使用逗号,

【讨论】:

这在扩展名相同的情况下很好。如果文件有不同的扩展名,它可以写成/path/to/files/\\file1.ext,file2.ext,file3.ext\\。注意 PowerShell 的人(现在 MS 已经加入了聚会)你需要使用 ` 来转义:/path/to/files/`file1.ext,file2.ext,file3.ext`【参考方案11】:

不使用scp更简单:

tar cf - file1 ... file_n | ssh user@server 'tar xf -'

这还允许您执行一些操作,例如压缩流 (-C) 或(自 OpenSSH v7.3 起)-J 以随时跳过一个(或多个)代理服务器。

通过将您的公钥复制到~/.ssh/authorized_keys(在服务器上)和ssh-copy-id(在客户端)来避免使用密码。

还发布了here(详细信息)和here。

【讨论】:

【参考方案12】:

注意:对于仅回答上述问题的一部分,我提前道歉。但是,我发现这些命令对我当前的 unix 需求很有用。

将特定文件从本地机器上传到远程机器:

~/Desktop/dump_files$ scp file1.txt file2.txt lab1.cpp etc.ext your-user-id@remotemachine.edu:Folder1/DestinationFolderForFiles/

将整个目录从本地机器上传到远程机器:

~$ scp -r Desktop/dump_files your-user-id@remotemachine.edu:Folder1/DestinationFolderForFiles/

将整个目录从远程机器下载到本地机器:

~/Desktop$ scp -r your-user-id@remote.host.edu:Public/web/ Desktop/

【讨论】:

【参考方案13】:

就我而言,我仅限于使用 sftp 命令。 所以,我不得不使用带有 sftp 的批处理文件。我创建了一个脚本,如下所示。这假设您在 /tmp 目录中工作,并且您希望将文件放在远程系统上的 destdir_on_remote_system 中。这也仅适用于非交互式登录。您需要设置公钥/私钥,以便无需输入密码即可登录。根据需要进行更改。

#!/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

【讨论】:

【参考方案14】:

在所有文件具有相同扩展名但具有不同后缀(例如日志文件数)的特定情况下,您可以使用以下内容:

scp user_name@ip.of.remote.machine:/some/log/folder/some_log_file.* ./

这将从远程中的给定文件夹中复制所有名为 some_log_file 的文件,即 - some_log_file.1 , some_log_file.2, some_log_file.3 ....

【讨论】:

【参考方案15】:
scp remote:"[A-C]/[12].txt" local:

【讨论】:

谢谢,但这只是一个例子,实际的文件或目录名称更复杂。但我有他们的清单。 你能用正则表达式来描述吗? 使用正则表达式是否可以在目标目录中保留相同的目录结构? 是的,您应该可以使用 -r 选项到 scp 来做到这一点。您可以使用-p 选项保留其他属性(如时间戳)。【参考方案16】:

scp 使用 ssh 进行具有相同身份验证的数据传输,并提供与 ssh 相同的安全性。

这里的最佳做法是实施“SSH KEYS AND PUBLIC KEY AUTHENTICATION”。有了这个,您可以编写脚本而无需担心身份验证。就这么简单。

见WHAT IS SSH-KEYGEN

【讨论】:

【参考方案17】:
serverHomeDir='/home/somepath/ftp/'
backupDirAbsolutePath=$serverHomeDir'_sqldump_'
backupDbName1='2021-08-27-03-56-somesite-latin2.sql'
backupDbName2='2021-08-27-03-56-somesite-latin1.sql'
backupDbName3='2021-08-27-03-56-somesite-utf8.sql'
backupDbName4='2021-08-27-03-56-somesite-utf8mb4.sql'

scp -i ~/.ssh/id_rsa.pub user@server.domain.com:$backupDirAbsolutePath/"$backupDbName1,$backupDbName2,$backupDbName3,$backupDbName4" .

。 - 最后将文件下载到当前目录

-i ~/.ssh/id_rsa.pub - 假设您使用 .pub 密钥建立了 ssh 到您的服务器

【讨论】:

以上是关于scp 或 sftp 使用单个命令复制多个文件的主要内容,如果未能解决你的问题,请参考以下文章

揭秘SFTP&&SCP命令 Linux详解

linux scp 命令能不能实现跳转复制?

scp命令和sftp命令

使用 Scp 时防止覆盖文件 [关闭]

WinSCP(5.11.2)绿色便携版,开源SCP/SFTP客户端

Linux下几种文件传输命令 sz rz sftp scp