如果目录不存在,scp 可以创建目录吗?

AGa*_*yer 137 scp

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

是否可以自动创建文件夹?如果是这样,如何?如果没有,我可以尝试什么替代方法?

War*_*ung 92

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

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

$ rsync -r local-dir remote-machine:path
Run Code Online (Sandbox Code Playgroud)

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

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

$ ssh remote-host 'mkdir -p foo/bar/qux'
Run Code Online (Sandbox Code Playgroud)

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

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


脚注:

  1. 在rsync2.6.0(2004 年 1 月 1 日)之前,它需要-e ssh标志使其表现得像,scp因为它默认为过时的RSH 协议。

  2. scp并rsync共享一些标志,但只有一点重叠。

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

  • @AwQiruiGuo:Mac OS X 附带了 `rsync`。是的,你也需要在远程端使用 `rsync`,就像使用 `scp` 一样。至于 SSH 密钥,`rsync` 实际上在底层使用 SSH 和默认的 `-e ssh`,所以如果你设置了用于 `scp` 的密钥,它们也适用于 `rsync`。 (2认同)

Joh*_*ohn 58

如果您正在复制一组文件,则不是。如果您要复制目录及其下面的所有内容,则可以。鉴于此命令:

$ scp -pr /source/directory user@host:the/target/directory
Run Code Online (Sandbox Code Playgroud)

如果directory在~/the/targeton中不存在host,它将被创建。但是,~the/target如果不存在,您可能会遇到问题 - 我不记得这个案例的确切结果,但要为预期scp的失败做好准备。

  • 来自“man scp”:“-p 保留原始文件的修改时间、访问时间和模式。” (6认同)
  • `scp: /home/madmike/test_bin: 没有这样的文件或目录` 一旦目标目录丢失,我的设置就会中断。在客户端上使用 cygwin,在服务器上使用 RHEL 6.9。你的设置是什么? (3认同)
  • 这应该是公认的答案,因为OP询问如何使用“scp”来做到这一点。接受的答案没有回答“我怎样才能用 scp 做到这一点?”的问题。此外,从实际的角度来看,当我尝试在禁用 rsync(synology)的计算机上执行此操作时,接受的答案对我来说也失败了。 (2认同)

ter*_*don 25

据我所知,scp它自己不能那样做,不。但是,您可以只ssh到目标机器,创建目录,然后复制。就像是:

ssh user@host "mkdir -p /target/path/" &&
    scp /path/to/source user@host:/target/path/
Run Code Online (Sandbox Code Playgroud)

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

scp -r ~/foo/ user@host:~/
Run Code Online (Sandbox Code Playgroud)

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


Stu*_*all 5

我在传输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
}
Run Code Online (Sandbox Code Playgroud)

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

check_remote_dir /my/remote/path