scp是否可以创建目录(如果不存在)?


88

我想使用scp上传文件,但有时目标目录可能不存在。

是否可以自动创建文件夹?如果是这样,怎么办?如果没有,我可以尝试其他替代方法吗?

Answers:


71

这是rsync可以做的许多事情之一。

如果您使用的rsync是过去几年发布的版本,¹其基本命令语法类似于scp

$ rsync -r local-dir remote-machine:path

这会将local-source其内容复制到$HOME/path/local-dir远程计算机上,从而创建所需的任何目录。³

rsync确实有一些限制可能会影响它在您的特定情况下是否有效。例如,它不会创建多个级别的丢失的远程目录;它只会在遥控器上最多创建一个丢失的级别。您可以通过在rsync命令之前添加类似以下内容来轻松解决此问题:

$ ssh remote-host 'mkdir -p foo/bar/qux'

$HOME/foo/bar/qux如果它不存在,那将创建树。它不会抱怨,或者如果它做任何事情坏已经存在。

rsync有时还有其他令人惊讶的行为。基本上,您是在要求它弄清楚您要复制的内容,其猜测可能与您的假设不符。试试看。如果它的行为不符合您的预期,并且您看不到原因,请发布有关本地和远程目录设置的更多详细信息,并提供您尝试的命令。


脚注

  1. rsync2.6.0 之前(2004年1月1日),它要求该-e ssh标志使其行为类似,scp因为它默认为过时的RSH协议

  2. scprsync共享一些标志,但是只有一点点重叠。

  3. SSH用作传输协议时,rsync使用相同的默认值。因此,就像一样scp,默认情况下,它将假定在远程计算机上有一个与本地用户同名的用户。


我正在使用Mac OSX,是否需要在本地和远程都安装rsync?
AGamePlayer 2015年

搜索rsync的文档页面,未找到如何使用ssh-key登录。我不想使用用户名/密码登录
AGamePlayer 2015年

@AwQiruiGuo:Mac OS X随附rsync。是的,rsync就像一样,您也确实需要远程scp。至于SSH密钥,rsync实际上是在默认情况下使用SSH -e ssh,因此,如果您设置了与一起使用的密钥scp,它们也将适用rsync
沃伦·杨

1
@WarrenYoung -r没有区别。您描述的方案仅在复制目录并且目标父目录存在的情况下才有效。因此,rsync foo/ u@h:~/将创建目标目录,foorsync foo/ u@h:~/bar/不会创建目标目录barbar/foo只有bar/存在时才会创建。无论如何,OP都在上传文件,即使在这种情况下,它也仅适用于整个目录。
terdon

1
是的,我也一直在玩。似乎指定文件名也会使其失败。所以rsync file host:/foo/file失败,如果foo/不存在,但rsync file host:/foo/创建目录和地方file在里面。奇怪。无论如何,您说的没错,基本方案可行,我将收回我的不赞成票。
terdon

35

如果要复制一组文件,则不是。如果要复制目录及其下的所有内容,则可以。给出以下命令:

$ scp -pr /source/directory user@host:the/target/directory

如果on directory中不存在,则会创建它。但是,如果不存在,您可能会遇到问题-我不记得这种情况的确切结果,但是要为失败做好准备。~/the/targethost~the/targetscp


1
scp: /home/madmike/test_bin: No such file or directory一旦目标目录丢失,这将破坏我的设置。在客户端上使用cygwin,在服务器上使用RHEL 6.9。你的设置是什么?
MadMike

16

据我所知,scp它本身不能做到这一点,不。但是,您可以仅ssh到目标计算机,创建目录,然后复制。就像是:

ssh user@host "mkdir -p /target/path/" &&
    scp /path/to/source user@host:/target/path/

请注意,如果要复制整个目录,则不需要上面的内容。例如,要将目录复制~/foo到远程主机,可以使用-r(递归)标志:

scp ~/foo/ user@host:~/

这将~/foo在远程主机上创建目标目录。但是,它无法创建父目录。scp ~/foo user@host:~/bar/foo除非目标目录bar存在,否则将失败。无论如何,-r如果您要复制单个文件,则该标志将无助于创建目标目录。


3

是的你可以。根据scp的手册页:

男子SCP

.....

-r递归复制整个目录。请注意,scp遵循在树遍历中遇到的符号链接。

....


7
那将不会创建目标父目录。它可以将目录复制到现有位置。因此,如果远程存在,scp -r foo/ u@h:~/bar将创建bar/foobar/但如果不存在则将失败。
terdon

1
它不会失败。它将foo内容复制到新目录/bar。当然,名称已更改,这可能不是OP想要的。如果您想要的是在目标计算机中创建的新树结构,scp则将无法执行该工作;如果您想要的是从树中的某个分支复制树结构,则将创建该结构。
YoMismo

6
是的,但这仅在复制目录而不是文件时有效。scp -r file host:~/bar/不会创建bar/
terdon

3

在转移btrfs快照之前,我使用以下功能ssh

check_remote_dir() {
        printf "\ntesting remote directory: '$1' "

        if ssh -p $PORT $ROOT@$REMOTE "[ ! -d $1 ]"; then
                printf "\nCreating: $1 on $ROOT@$REMOTE\n"
                ssh -p $PORT $ROOT@$REMOTE "mkdir -p $1"
        else
                printf "[OK]\n"
        fi
}

只需使用以下命令在脚本中调用该函数:

check_remote_dir /my/remote/path


我几乎做同样的事情,但是出于安全原因,我必须手动输入密码,所以我最终至少要输入两次...
Stefan Reich

0

您可以将命令与mkdir命令链接在一起,然后引用您创建的文件夹:

mkdir ~/new-folder/ && scp -P 22 <remote/url>:~/new-folder/

3
(1)问题是“自动”。这似乎不是自动的。(2)这似乎只是terdon答案的琐碎变化。
G-Man

0

当限制为仅scp或sftp且没有可用的ssh时(由rssh启用),可以通过使用rsync复制空目录树然后复制文件来创建目录。

当ssh-copy-id不起作用并且.ssh目录不存在时,这就是我将公用ssh密钥放置到远程主机的方式:

rsync -e 'ssh -p22' -av -f"+ */" -f"- *" ~/.ssh backup@1.2.3.4:~/
scp -P22 ~/.ssh/id_rsa.pub backup@1.2.3.4:~/.ssh/authorized_keys

如果目标文件名相同,则可以将此命令组合为一个rsync,并在中间添加一个include过滤器。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.