Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

When I run svn st | awk '{print $2}', I get:

a.py
b.py
c.py

Then I want to scp these files to a remote server. I have tried:

svn st | awk '{print $2}' | xargs scp my_name@my_server:~/

But it doesn't work. What is the right command to do this?

Thank you!

share|improve this question

2 Answers 2

up vote 7 down vote accepted

try this. should work with recent versions of xargs.

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

alternately, you could just loop though the files.

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

share|improve this answer
1  
Thank you Tim. I googled a lot and found the solution: svn st | awk '{print $2}' | xargs -J % scp % my_name@my_server:~/ I should have read the man page of xargs before asking ;) –  mitnk Nov 18 '11 at 6:14
    
And your solution works too! But there is a typo, it's -Iz not -iz –  mitnk Nov 18 '11 at 6:19
    
what OS are you using? I use -iz on Solaris, and it always works. Thanks for the pointer. –  Tim Kennedy Nov 18 '11 at 6:28
2  
POSIX xargs has -I. The AIX (6.1) man page says -i is obsolete and -I should be used. Solaris 10 (and 9) has both -i and -I. –  Mat Nov 18 '11 at 11:21
1  
Ah, my knowledge is obsolete! I've been using -i since Solaris 2.5. getting old is a sad affair, my friends. :) –  Tim Kennedy Nov 18 '11 at 13:36

The reason this doesn't work is that you're telling xargs to run

scp my_name@my_server:~/ a.py b.py c.py

The order of the arguments doesn't correspond to what you want to do. One solution is to force the file names to appear before the destination on the command line. This requires GNU xargs (i.e. Linux or Cygwin). While we're at it, we can pass -d '\n' to ensure that any file name that doesn't contain newlines will work (without -d, xargs expects some weird quoting of its input); this is not necessary if you work with typical software source trees, in which file names tend to be very tame.

svn st | awk '{print $2}' |
xargs -d\\n -I{} scp {} my_name@my_server:~/

A downside of this method is that scp is called separately for every file. If you're copying a lot of small files, that can make a significant difference, as an SSH connection takes a little while to establish. You can greatly shorten the per-connection time by using an SSH master connection (that's outstide the scope of this answer, see the manual, especially the ControlMaster and ControlPath options in .ssh/config).

A way to force the arguments to be in the right place is to go through an intermediate shell. This is a general technique to reorder arguments when using xargs or find … -exec.

svn st | awk '{print $2}' |
xargs -d\\n sh -c 'scp "$@" "$0" my_name@my_server:~/

Another possibility is to use rsync instead of scp. You can pass rsync a list of file names on standard input. Since rsync expects a list of patterns and not a list of file names, this requires that your file names do not contain any wildcard characters (specifically, no newlines, no \[*? and no initial # or ;).

svn st | awk '{print $2}' |
rsync -a --include-from=- --exclude='*' . my_name@my_server:~/
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.