为什么“scp 10.0.0.11:/home/someuser/.*”也开始从/home复制?

Bri*_*ian 15 scp directory path pwd

我正在第一次将用户文件从旧系统移动到新系统。我的目标是使用 SCP,因为它的语法简单scp -r source destination。我首先尝试使用以下命令来复制文件:

scp -r root@10.0.0.11:/home/someuser/* .
Run Code Online (Sandbox Code Playgroud)

回想起来,根据过去的经验,这复制了所有没有前导.. 为了解决这个问题,我这样做了:

scp -r root@10.0.0.11:/home/someuser/.* .
Run Code Online (Sandbox Code Playgroud)

表示以 . 开头的任何内容的通配符.。显然(为什么我问这个问题)它没有达到我想要的效果。观察到的结果是,它将解释为.在路径中向上移动一个级别,并且它开始复制/home/*,并且(我认为)将文件放置在我的工作目录之上,而不是工作目录本身。

我对第二个命令执行的解释是否正确?我认为自从我进入以来就很容易修复~/backup,所以升级了一级~。我只是rm -rf ~/someuser在中断命令之前复制的每个用户名。这些someuser目录应该位于~/backup

从那以后,我学会了如何通过仅指定目录而不是目录中包含的文件来复制我想要的文件。

ilk*_*chu 32

并不是.上一层,而是在 shell 的模式匹配语法中,意思*是任意数量的任意字符,因此它匹配..每个目录中存在的条目并指向下一个上层目录。ls .*您可以使用 Bash 和许多其他 shell获得相同的效果。

匹配.*特殊条目...一种痛苦,而且永远没有用。您可能会看到人们使用丑陋的解决方法,例如在条目.??* .[!.]中显式导航..(*)

幸运的是,一些更智能的 shell 从 glob 结果中删除了这两个,zsh 可能是最突出的,但不是唯一的。(至少 Bash 的开发版本也有这个选项globskipdots。)

在这种特殊情况下,由于 SSH 服务器扩展了 glob,因此更加复杂,但我预计根本原因是相同的。

(*.??*匹配一个点和至少两个其他字符,.[!.]匹配一个点和一个非点的字符。在正则表达式中,*?的含义略有不同。)

  • 尼克博士:你的意思是 .* 包括 .. ?多么一个国家啊!这是一个非常清晰和简洁的答案。也许我也错误地记住了我的工作目录,所以这可能会让我感到困惑。不管怎样,我需要更多地理解通配符。我将它与 rdiff-backup 一起使用,但没有探索这些明显的复杂性。 (2认同)
  • 在贝壳中,还有 Forsyth 贝壳及其衍生物,包括 pdksh 及其衍生物和鱼。请注意,我们知道 OP 不会在本地主机上使用 zsh,因为不带引号的“*”会导致错误,除非其中存在“root@10.0.0.11:/home/someuser”目录和文件。 (2认同)
  • @Brian,同样在 bash 中,您需要确保引用“*”,因为您不希望本地 shell 将“*”解释为 glob 运算符,而是将其传递给 scp,以便删除 scp/sftp 端解释该通配符 (2认同)