Usar scp -v
mostra alguns detalhes sobre como o scp funciona:
debug1: Sending command: scp -v -t /tmp/A$2.class
Sending file modes: C0644 0 A$2.class
Sink: C0644 0 A$2.class
A$2.class 100% 0 0.0KB/s 00:00
Essencialmente, como o scp é executado sobre o ssh, ele precisa de um shell para executar seu comando e, como o $
não é ignorado, o shell remoto interpreta $2
como uma string vazia, o que torna o nome de destino A.class
.
Existem duas maneiras de resolver isso. Primeiro, você poderia simplesmente usar o *
glob no seu comando scp diretamente:
scp * foo@bar:/tmp/
Mas eu tenho certeza que você tem alguma outra necessidade de usar um loop, então aqui está como corrigi-lo no loop:
for i in *; do
scp "${i}" "foo@bar:'/tmp/${i}'"
done
Verificando a saída de scp -v
agora mostra:
debug1: Sending command: scp -v -t '/tmp/A$2.class'
Sucesso! As aspas simples impedirão que o shell remoto execute a expansão de variáveis.
ATUALIZAÇÃO: Como o argumento é interpretado pelo shell como um argumento, você pode fazer coisas assim:
scp foo@bar:'$(which ssh)' .
Ou pipelines de shell ainda mais complicados que resultam em um nome de arquivo. Isso não é um problema de segurança, pois se você pode se conectar com o scp, você pode se conectar com o ssh. Mas isso pode tornar as coisas mais convenientes para alguém.