Может ли scp создать каталог, если он не существует?

89

Я хочу использовать scpдля загрузки файлов, но иногда целевой каталог может не существовать.

Можно ли создать папку автоматически? Если так, то как? Если нет, какой альтернативный способ я могу попробовать?

AGamePlayer
источник

Ответы:

72

Это одна из многих вещей, которые rsyncможно сделать.

Если вы используете версию, rsyncвыпущенную в последние несколько лет, basic основной синтаксис команды похож на scp: ²

$ rsync -r local-dir remote-machine:path

Он будет копировать local-sourceего содержимое $HOME/path/local-dirна удаленную машину, создавая все необходимые каталоги.

rsyncздесь есть некоторые ограничения, которые могут повлиять на то, будет ли это работать в вашей конкретной ситуации. Например, он не создаст несколько уровней отсутствующих удаленных каталогов; он создаст только один пропущенный уровень на пульте дистанционного управления. Вы можете легко обойти это, предваряя rsyncкоманду чем-то вроде этого:

$ ssh remote-host 'mkdir -p foo/bar/qux'

Это создаст $HOME/foo/bar/quxдерево, если оно не существует. Он не будет жаловаться или сделать что - нибудь еще плохо , если это действительно уже существует.

rsyncиногда имеет другое удивительное поведение. По сути, вы просите его выяснить, что вы хотели скопировать, и его догадки могут не соответствовать вашим предположениям. Попробуйте и посмотрите. Если он работает не так, как вы ожидаете, и вы не можете понять, почему, опубликуйте более подробную информацию о настройках вашего локального и удаленного каталога и введите команду, которую вы попробовали.


Сноски :

  1. До rsync2.6.0 (1 января 2004 г.) -e sshфлаг требовал, чтобы он вел себя как, scpпотому что по умолчанию использовался устаревший протокол RSH .

  2. scpи rsyncподелиться некоторыми флагами, но есть только частичное совпадение.

  3. При использовании SSHв качестве протокола передачи, rsyncиспользуются те же значения по умолчанию. Так что, точно так же scp, он будет предполагать, что по умолчанию на удаленном компьютере есть пользователь с тем же именем, что и у вашего локального пользователя.

Уоррен Янг
источник
Я использую Mac OSX, нужно ли устанавливать rsync как на локальной, так и на удаленной стороне?
AGamePlayer
искал rsyncстраницу документации, не нашел как использовать ssh-ключ для входа. Я не хочу использовать имя пользователя / пароль для входа в систему
AGamePlayer
1
@AwQiruiGuo: Mac OS X поставляется с rsync. И да, вам тоже нужно rsyncна удаленной стороне, как и с scp. Что касается ключей SSH, rsyncна самом деле используется SSH со значением по умолчанию -e ssh, поэтому, если у вас есть ключи, настроенные для использования с ними scp, они также будут работать rsync.
Уоррен Янг
1
@WarrenYoung -rне имеет значения. Сценарий, который вы описываете, работает, только если вы копируете каталог и существует целевой родительский каталог. Итак, rsync foo/ u@h:~/создаст целевой каталог, fooно rsync foo/ u@h:~/bar/не создаст целевой каталог bar. Тот создаст bar/fooтолько если bar/существует. В любом случае, OP загружает файлы и даже в тех случаях, когда это работает, он работает только для целых каталогов.
Terdon
1
Да, я тоже играл с этим. Кажется, что указание имени файла также делает его неудачным. Так что rsync file host:/foo/fileтерпит неудачу, если foo/не существует, но rsync file host:/foo/создает каталог и помещает fileв него. Странный. В любом случае, вы совершенно правы, и основной сценарий работает, я откажусь от своего отрицательного мнения.
Тердон
35

Если вы копируете группу файлов, не совсем. Если вы копируете каталог и все содержимое под ним, да. Учитывая эту команду:

$ scp -pr /source/directory user@host:the/target/directory

Если directoryне существует в ~/the/targeton host, он будет создан. Если, однако, ~the/targetне существует, у вас, скорее всего, будут проблемы - я не помню точные результаты этого случая, но будьте готовы к тому, scpчто он потерпит неудачу.

Джон
источник
1
scp: /home/madmike/test_bin: No such file or directoryКак только целевой каталог отсутствует, это нарушает мои настройки. Использование cygwin на клиенте и RHEL 6.9 на сервере. Каковы ваши настройки?
MadMike
16

Насколько я знаю, scpсам не может этого сделать, нет. Тем не менее, вы можете просто sshна целевой машине, создать каталог, а затем скопировать. Что-то вроде:

ssh user@host "mkdir -p /target/path/" &&
    scp /path/to/source user@host:/target/path/

Обратите внимание, что если вы копируете целые каталоги, вышеописанное не требуется. Например, чтобы скопировать каталог ~/fooна удаленный хост, вы можете использовать -r(рекурсивный) флаг:

scp ~/foo/ user@host:~/

Это создаст целевой каталог ~/fooна удаленном хосте. Тем не менее, он не может создать родительский каталог. scp ~/foo user@host:~/bar/fooпотерпит неудачу, если целевой каталог не barсуществует. В любом случае -rфлаг не поможет создать целевой каталог, если вы копируете отдельные файлы.

Тердон
источник
3

Да, ты можешь. Согласно справочной странице scp:

человек scp

.....

-r Рекурсивно копировать целые каталоги. Обратите внимание, что scp следует символическим ссылкам, встречающимся при обходе дерева.

....

YoMismo
источник
7
Это не создаст целевой родительский каталог. Он может скопировать каталог в существующее местоположение. Таким образом, scp -r foo/ u@h:~/barбудет bar/fooсоздан, если удаленный bar/существует, но потерпит неудачу, если это не так.
Terdon
1
Это не подведет. Он скопирует fooсодержимое в новый каталог /bar. Конечно, имя было изменено, что не может быть тем, что хочет ОП. Если вам нужна новая древовидная структура, созданная на конечном компьютере, тогда работа scpне будет выполняться, если вам нужно скопировать древовидную структуру из определенной ветви дерева, то эта структура будет создана.
YoMismo
6
Да, но это работает, только если вы копируете каталоги , а не файлы. scp -r file host:~/bar/не будет создавать bar/.
Terdon
3

Я использую следующую функцию перед передачей btrfsснимков ssh:

check_remote_dir() {
        printf "\ntesting remote directory: '$1' "

        if ssh -p $PORT $ROOT@$REMOTE "[ ! -d $1 ]"; then
                printf "\nCreating: $1 on $ROOT@$REMOTE\n"
                ssh -p $PORT $ROOT@$REMOTE "mkdir -p $1"
        else
                printf "[OK]\n"
        fi
}

Просто вызовите функцию в вашем скрипте с помощью:

check_remote_dir /my/remote/path

Стюарт Кардалл
источник
Я делаю почти то же самое, но мне приходится вводить пароль вручную (из соображений безопасности), поэтому я в итоге набираю его как минимум дважды ...
Стефан Райх
0

Вы можете связать команду с командой mkdir, а затем сослаться на созданную вами папку:

mkdir ~/new-folder/ && scp -P 22 <remote/url>:~/new-folder/
душка
источник
3
(1) Вопрос говорит «автоматически». Это не кажется автоматическим. (2) Это, кажется, только тривиальная вариация ответа Тердона .
G-Man
0

Когда ограничено только scp или sftp без ssh (по rssh), можно создавать каталоги, копируя пустое дерево каталогов с помощью rsync, а затем копируя файлы.

Вот как я помещаю открытый ключ ssh на удаленный хост, когда ssh-copy-id не работает и каталог .ssh не существует:

rsync -e 'ssh -p22' -av -f"+ */" -f"- *" ~/.ssh backup@1.2.3.4:~/
scp -P22 ~/.ssh/id_rsa.pub backup@1.2.3.4:~/.ssh/authorized_keys

Можно объединить эти команды в один rsync, добавив еще один фильтр включения в середине, если имя целевого файла совпадает.

user3132194
источник