O scp pode criar um diretório se ele não existir?

89

Quero usar o scpupload de arquivos, mas às vezes o diretório de destino pode não existir.

É possível criar a pasta automaticamente? Se sim, como? Caso contrário, que maneira alternativa posso tentar?

AGamePlayer
fonte

Respostas:

72

Essa é uma das muitas coisas que rsyncpodemos fazer.

Se você estiver usando uma versão rsynclançada nos últimos anos, ¹ sua sintaxe básica de comando é semelhante a scp: ²

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

Isso copiará local-sourcee seu conteúdo para $HOME/path/local-dira máquina remota, criando os diretórios necessários.³

rsyncpossui algumas restrições aqui que podem afetar se isso funcionará em sua situação específica. Não criará vários níveis de diretórios remotos ausentes, por exemplo; ele criará apenas um nível ausente no controle remoto. Você pode contornar isso facilmente precedendo o rsynccomando com algo como isto:

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

Isso criará a $HOME/foo/bar/quxárvore se ela não existir. Não vai reclamar ou fazer qualquer outra coisa ruim se ele não existir.

rsyncàs vezes tem outros comportamentos surpreendentes. Basicamente, você está pedindo para descobrir o que pretende copiar, e suas suposições podem não corresponder às suas suposições. Experimente e veja. Se não se comportar conforme o esperado e você não conseguir entender o motivo, poste mais detalhes sobre as configurações de diretório local e remoto e dê o comando que você tentou.


Notas de rodapé :

  1. Antes da rsyncversão 2.6.0 (1 de janeiro de 2004), era necessário que o -e sshsinalizador se comportasse como scppadrão, porque o padrão era o obsoleto protocolo RSH .

  2. scpe rsynccompartilhe algumas bandeiras, mas há apenas um pouco de sobreposição.

  3. Ao usar SSHcomo protocolo de transferência, rsyncusa os mesmos padrões. Assim, da mesma forma scp, assumirá que há um usuário com o mesmo nome que o usuário local na máquina remota por padrão.

Warren Young
fonte
Estou usando o Mac OSX, preciso instalar o rsync no lado local e remoto?
AGamePlayer
rsyncpágina de documentação da pesquisa , não encontrou como usar o ssh-key para fazer login. Eu não quero usar nome de usuário / senha para fazer login
AGamePlayer 30/03
1
@AwQiruiGuo: O Mac OS X vem com rsync. E sim, você também precisa rsyncdo lado remoto, assim como com scp. Quanto às chaves SSH, rsyncna verdade , ela está usando o SSH abaixo do padrão -e ssh; portanto, se você tiver chaves configuradas para uso scp, elas funcionarão rsynctambém.
Warren Young
1
@WarrenYoung -rnão faz diferença. O cenário que você descreve apenas funciona se você estiver copiando um diretório e se o diretório pai de destino existir. Portanto, rsync foo/ u@h:~/criará o diretório de destino, foomas rsync foo/ u@h:~/bar/não o criará bar. Esse criará bar/fooapenas se bar/existir. De qualquer forma, o OP está carregando arquivos e, mesmo nos casos em que isso funciona, funciona apenas para diretórios inteiros.
terdon
1
Sim, eu também brinco com isso. Parece que especificar um nome de arquivo também faz com que ele falhe. Portanto, rsync file host:/foo/filefalha se foo/não existir, mas rsync file host:/foo/cria o diretório e os locais filenele. Estranho. De qualquer forma, você está certo e o cenário básico funciona, eu retiro meu voto negativo.
terdon
35

Se você estiver copiando um grupo de arquivos, na verdade não. Se você estiver copiando um diretório e todo o conteúdo abaixo dele, sim. Dado este comando:

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

Se directorynão existir no ~/the/targetno host, ele será criado. Se, no entanto, ~the/targetnão existir, você provavelmente terá problemas - não me lembro dos resultados exatos deste caso, mas esteja preparado para a scpfalha pretendida .

John
fonte
1
scp: /home/madmike/test_bin: No such file or directoryAssim que o diretório de destino estiver ausente, isso será interrompido na minha instalação. Usando o cygwin no cliente e o RHEL 6.9 no servidor. Qual é a sua configuração?
MadMike 12/02
16

Tanto quanto eu sei, scpele próprio não pode fazer isso, não. No entanto, você pode apenas sshpara a máquina de destino, criar o diretório e depois copiar. Algo como:

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

Observe que, se você estiver copiando diretórios inteiros, o acima não será necessário. Por exemplo, para copiar o diretório ~/foopara o host remoto, você pode usar o -rsinalizador (recursivo):

scp ~/foo/ user@host:~/

Isso criará o diretório de destino ~/foono host remoto. No entanto, ele não pode criar o diretório pai. scp ~/foo user@host:~/bar/foofalhará a menos que o diretório de destino barexista. De qualquer forma, o -rsinalizador não ajudará a criar um diretório de destino se você estiver copiando arquivos individuais.

terdon
fonte
3

Sim você pode. De acordo com a página de manual do scp:

man scp

.....

-r Copia recursivamente diretórios inteiros. Observe que o scp segue links simbólicos encontrados no percurso da árvore.

....

YoMismo
fonte
7
Isso não criará o diretório pai de destino. Ele pode copiar um diretório para um local existente. Portanto, scp -r foo/ u@h:~/barcriará bar/foose o controle remoto bar/existir, mas falhará se não existir.
terdon
1
Não falhará. Ele copiará o fooconteúdo para o novo diretório /bar. É claro que o nome foi alterado, o que pode não ser o que o OP deseja. Se o que você deseja é uma nova estrutura em árvore criada na máquina de destino, então scpnão fará o trabalho, se o que você deseja é replicar uma estrutura em árvore a partir de uma determinada ramificação na árvore, essa estrutura será criada.
YoMismo 30/03
6
Sim, mas isso só funciona se você estiver copiando diretórios , não arquivos. scp -r file host:~/bar/não criará bar/.
terdon
3

Eu uso a seguinte função antes de transferir btrfsinstantâneos 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
}

Basta chamar a função no seu script com:

check_remote_dir /my/remote/path

Stuart Cardall
fonte
I fazer praticamente a mesma coisa, mas eu tenho que digitar a senha manualmente (por razões de segurança), assim que eu acabar digitando-o pelo menos duas vezes ...
Stefan Reich
0

Você pode encadear o comando com o comando mkdir e fazer referência à pasta que você criou:

mkdir ~/new-folder/ && scp -P 22 <remote/url>:~/new-folder/
Ducky
fonte
3
(1) A pergunta diz "automaticamente". Isso não parece automático. (2) Parece ser apenas uma variação trivial da resposta de Terdon .
G-Man
0

Quando restrito a apenas scp ou sftp sem ssh disponível (por rssh), é possível criar diretórios copiando a árvore de diretórios vazia com o rsync e depois copiando os arquivos.

É assim que eu coloco a chave pública ssh no host remoto quando ssh-copy-id não funciona e o diretório .ssh não existe:

rsync -e 'ssh -p22' -av -f"+ */" -f"- *" ~/.ssh [email protected]:~/
scp -P22 ~/.ssh/id_rsa.pub [email protected]:~/.ssh/authorized_keys

É possível combinar esses comandos em um rsync, adicionando mais um filtro de inclusão no meio, se o nome do arquivo de destino for o mesmo.

user3132194
fonte