Como passar o argumento com char (no caminho remoto?

2

Estou tentando mover um arquivo com o rsync para um local remoto,

O arquivo tem o nome: DRRS_ (H264) .mp4

mas quando tento:

rsync -azR output.mp4 [email protected]:encoded/somepath/DRRS_(H264).mp4

diz: bash: erro de sintaxe próximo ao token inesperado '('

Mas não entendo como devo encapsular isso.

Eu tentei:

rsync -azR output.mp4 [email protected]:"encoded/somepath/DRRS_(H264).mp4"

e

rsync -azR output.mp4 "[email protected]:encoded/somepath/DRRS_(H264).mp4"

sem sucesso.

    
por Vincent Duprez 21.07.2015 / 13:24

3 respostas

7

Você deseja usar a opção -s|--protect-args para rsync .

Sem ele, a parte após o : é passada como está para o shell remoto, então você pode usar construções desse shell para construir a lista a ser transferida.

Dessa forma, se você sabe que o shell remoto é zsh, por exemplo, você pode fazer:

rsync host:'*(.)' there

para transferir apenas arquivos regulares. Ou com csh / bash / zsh / ksh :

rsync host:'{foo,bar}.txt' there

Ou:

rsync file 'host:"$HOME/$(uname)-file"'

Agora, isso significa que você não pode transferir arquivos com um nome arbitrário.

Com -s , rsync não passa a string para o shell remoto. Em vez disso, ele passa em banda para o servidor rsync no host remoto, portanto não há interpretação pelo shell remoto.

( e ) sendo especiais para a maioria dos shells, você teria que escapar usando a sintaxe do shell remoto, e isso varia de shell para shell.

O melhor é usar -s .

rsync -sazR output.mp4 [email protected]:'encoded/somepath/DRRS_(H264).mp4'

No entanto, rsync ainda executa (sua própria) globbing na string que você passa (mesmo para o destino!). Então você ainda não pode passar nomes de arquivos arbitrários com rsync . Se você quiser processar um arquivo chamado * , por exemplo, você precisa escapar com barra invertida (pelo menos, desta vez, independentemente do shell remoto).

rsync -sazR output.mp4 [email protected]:'\*'

Então, para transferir um arquivo com um nome arbitrário contido em $1 , você vai querer usar:

file=$1
rsync_escaped_file=$(
  printf '%s.\n' "$file" | sed 's/[[*?]/\&/g'
)
rsync_escaped_file=${rsync_escaped_file%.}
rsync -s ... "user@host:$rsync_escaped_file"

Se o seu shell local for bash e você souber que o shell de login do usuário remoto também é bash da mesma versão, alternativamente, você pode usar printf %q para escapar dos caracteres especiais do shell remoto e não use -s :

LC_ALL=C printf -v shell_escaped_file %q "$1"
rsync ... "user@host:$shell_escaped_file"

Se você sabe que o shell de login do host remoto é parecido com Bourne (Bourne, ksh, yash, zsh, bash, ash ...) e seu cliente e servidor ssh permite passar LC_* de variáveis de ambiente, você também pode do (novamente, sem -s ):

LC_FILE=$1 rsync ... 'user@host:"$LC_FILE"'

Note1 : a opção -s | --protect-args está disponível apenas na versão 3.0.0 (2008) ou acima

Note2 : a documentação rsync avisa que -s | --protect-args pode se tornar o padrão em versões futuras de rsync (para ser à prova do futuro, você pode deseja começar a usar --no-protect-args se você não quiser seu efeito)

    
por 21.07.2015 / 14:17
3

Experimente o abaixo, testei isso e está funcionando. Você deve citar seu caminho de destino com ' ou " e deve escapar do ( e ) .

rsync -azR output.mp4 [email protected]:'encoded/somepath/DRRS_\(H264\).mp4'

UPDATE:

Ligue para o seu script como abaixo,

./sample.sh "encoded/somepath/DRRS_\(H264\).mp4"

sample.sh

 #!/bin/bash
 rsync -azR output.mp4 [email protected]:"$1"
    
por 21.07.2015 / 13:41
2

Você precisa citar o caminho e usar uma barra invertida para escapar parênteses no caminho remoto.

Aspas simples ou duplas funcionarão.

rsync -azR output.mp4 [email protected]:"encoded/somepath/DRRS_\(H264\).mp4"

OR

rsync -azR output.mp4 [email protected]:'encoded/somepath/DRRS_\(H264\).mp4'

    
por 21.07.2015 / 13:42