使用 xargs 向 scp 提供参数

mit*_*tnk 10 scp xargs

当我运行时svn st | awk '{print $2}',我得到:

a.py
b.py
c.py
Run Code Online (Sandbox Code Playgroud)

然后我想将scp这些文件传送到远程服务器。我试过了:

svn st | awk '{print $2}' | xargs scp my_name@my_server:~/
Run Code Online (Sandbox Code Playgroud)

但它不起作用。执行此操作的正确命令是什么?

谢谢!

Tim*_*edy 11

尝试这个。应该适用于最新版本的 xargs。

svn st | awk '{print $2}' | xargs -iz scp z my_name@my_server:

或者,您可以循环遍历文件。

for file in $(svn st | awk '{print $2}'); do scp $file my_name@my_server: ; done

  • [POSIX xargs](http://pubs.opengroup.org/onlinepubs/000095399/utilities/xargs.html) 有`-I`。AIX (6.1) 手册页说`-i` 已过时,应该使用`-I`。Solaris 10(和 9)同时具有 `-i` 和 `-I`。 (4认同)
  • 谢谢蒂姆。我用谷歌搜索了很多,找到了解决方案:`svn st | awk '{print $2}' | xargs -J % scp % my_name@my_server:~/` 我应该在问之前阅读 `xargs` 的手册页 ;) (2认同)

Gil*_*il' 5

这不起作用的原因是你告诉xargs运行

\n\n
scp my_name@my_server:~/ a.py b.py c.py\n
Run Code Online (Sandbox Code Playgroud)\n\n

参数的顺序与您想要执行的操作不符。一种解决方案是强制文件名出现在命令行上的目标之前。这需要 GNU xargs(即 Linux 或 Cygwin)。当我们这样做时,我们可以通过传递-d \'\\n\'来确保任何不包含换行符的文件名都可以工作(没有-d, xargs 期望对其输入进行一些奇怪的引用);如果您使用典型的软件源代码树(其中文件名往往非常温和),则没有必要这样做。

\n\n
svn st | awk \'{print $2}\' |\nxargs -d\\\\n -I{} scp {} my_name@my_server:~/\n
Run Code Online (Sandbox Code Playgroud)\n\n

此方法的缺点是scp为每个文件单独调用。如果您要复制大量小文件,这可能会产生重大影响,因为建立 SSH 连接需要一些时间。您可以通过使用 SSH 主连接来大大缩短每个连接的时间(这超出了本答案的范围,请参阅手册,尤其是中的ControlMasterControlPath选项.ssh/config)。

\n\n

强制参数位于正确位置的一种方法是通过中间 shell。xargs这是使用or时对参数重新排序的通用技术find \xe2\x80\xa6 -exec

\n\n
svn st | awk \'{print $2}\' |\nxargs -d\\\\n sh -c \'scp "$@" "$0" my_name@my_server:~/\n
Run Code Online (Sandbox Code Playgroud)\n\n

另一种可能性是使用rsync代替scp. 您可以rsync在标准输入上传递文件名列表。由于rsync需要模式列表而不是文件名列表,因此这要求您的文件名不包含任何通配符(具体来说,没有换行符,没有且\\[*?没有首字母#;)。

\n\n
svn st | awk \'{print $2}\' |\nrsync -a --include-from=- --exclude=\'*\' . my_name@my_server:~/\n
Run Code Online (Sandbox Code Playgroud)\n