Forneça parâmetros para scp com xargs

10

Quando corro svn st | awk '{print $2}', recebo:

a.py
b.py
c.py

Então eu quero scpesses arquivos para um servidor remoto. Eu tentei:

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

Mas isso não funciona. Qual é o comando certo para fazer isso?

Obrigado!

mitnk
fonte

Respostas:

10

tente isso. deve funcionar com versões recentes do xargs.

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

alternativamente, você pode simplesmente repetir os arquivos.

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

Tim Kennedy
fonte
2
Obrigado Tim. Eu pesquisei muito e encontrou a solução: svn st | awk '{print $2}' | xargs -J % scp % my_name@my_server:~/Eu deveria ter ler a página homem de xargsantes de pedir;)
mitnk
E sua solução também funciona! Mas há um erro de digitação, é -Iznão-iz
mitnk
qual sistema operacional você está usando? Eu uso -izno Solaris, e sempre funciona. Obrigado pelo ponteiro.
Tim Kennedy
4
POSIX xargs possui -I. A página do manual AIX (6.1) diz que -iestá obsoleta e -Ideve ser usada. O Solaris 10 (e 9) possui ambos -ie -I.
Mat
11
Ah, meu conhecimento é obsoleto! Uso -idesde o Solaris 2.5. envelhecer é um assunto triste, meus amigos. :)
Tim Kennedy
4

A razão pela qual isso não funciona é que você está dizendo xargspara executar

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

A ordem dos argumentos não corresponde ao que você deseja fazer. Uma solução é forçar os nomes dos arquivos a aparecerem antes do destino na linha de comando. Isso requer GNU xargs (ou seja, Linux ou Cygwin). Enquanto estamos nisso, podemos passar -d '\n'para garantir que qualquer nome de arquivo que não contenha novas linhas funcione (sem -d, o xargs espera algumas citações estranhas de sua entrada); isso não é necessário se você trabalhar com árvores de origem de software típicas, nas quais os nomes de arquivos tendem a ser muito mansos.

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

Uma desvantagem desse método é que scpé chamado separadamente para cada arquivo. Se você estiver copiando muitos arquivos pequenos, isso pode fazer uma diferença significativa, pois uma conexão SSH demora um pouco para ser estabelecida. Você pode reduzir bastante o tempo por conexão usando uma conexão mestre SSH (que está além do escopo desta resposta, consulte o manual, especialmente as opções ControlMastere ).ControlPath.ssh/config

Uma maneira de forçar os argumentos a estarem no lugar certo é passar por um shell intermediário. Essa é uma técnica geral para reordenar argumentos ao usar xargsou find … -exec.

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

Outra possibilidade é usar em rsyncvez de scp. Você pode passar rsyncuma lista de nomes de arquivos na entrada padrão. Como rsyncespera uma lista de padrões e não uma lista de nomes de arquivos, isso exige que os nomes de arquivos não contenham caracteres curinga (especificamente, sem novas linhas, sem \[*?e sem inicial #ou ;).

svn st | awk '{print $2}' |
rsync -a --include-from=- --exclude='*' . my_name@my_server:~/
Gilles 'SO- parar de ser mau'
fonte