Назад | Перейти на главную страницу

SCP заменяет файлы знаками доллара

У меня есть такие файлы:

A.class
A$1.class
A$2.class

И сценарий bash с чем-то вроде:

for i in *; do
    scp "${i}" foo@bar:/tmp/;
done

Это прекрасно работает. Копируются все три файла. Проблема в следующем:

for i in *; do
    scp "${i}" foo@bar:/tmp/"${i}";
    scp "${i}" foo@bar:"/tmp/${i}";
    scp "${i}" "foo@bar:/tmp/${i}";
done

В любом из этих случаев SCP копирует все файлы, но в тот же файл. Класс.

Любые идеи? Спасибо!

С помощью scp -v показывает некоторые подробности о том, как работает scp:

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    

По сути, поскольку scp работает поверх ssh, ему нужна оболочка для выполнения вашей команды, а поскольку $ не экранирован, удаленная оболочка интерпретирует $2 как пустая строка, что делает целевое имя A.class.

Есть два способа исправить это. Во-первых, вы можете просто использовать * glob напрямую в команду scp:

scp * foo@bar:/tmp/

Но я почти уверен, что у вас есть другие потребности в использовании цикла, поэтому вот как исправить это в цикле:

for i in *; do
    scp "${i}" "foo@bar:'/tmp/${i}'"
done

Проверка вывода scp -v теперь показывает:

debug1: Sending command: scp -v -t '/tmp/A$2.class'

Успех! Одиночные кавычки не позволяют удаленной оболочке выполнять раскрытие переменных.

ОБНОВЛЕНИЕ: поскольку аргумент интерпретируется оболочкой как аргумент, вы можете делать такие вещи, как это:

scp foo@bar:'$(which ssh)' .

Или даже более сложные конвейеры оболочки, которые приводят к имени файла. Это не проблема безопасности, так как если вы можете подключиться с помощью scp, вы можете подключиться с помощью ssh. Но кому-то это может сделать жизнь удобнее.

Одним из решений было бы использовать для этого find:

find . -name A\*.class -print0|xargs -0 -i _PLACEHOLDER_ scp _PLACEHOLDER_ foo@bar:/tmp/_PLACEHOLDER_

Идея состоит в том, чтобы избежать расширения оболочки.

Я думаю это вызвано "${i}" расширяется на местном уровне до A$1.class а затем отправляется на пульт, который расширяет его до A.class как $1 является "". Вы можете обойти это с

scp "${i}" foo@bar:/tmp/'${i}';