web-dev-qa-db-ja.com

scpは、存在しないディレクトリを作成できますか?

scpを使用してファイルをアップロードしたいのですが、ターゲットディレクトリが存在しない場合があります。

フォルダを自動的に作成することはできますか?もしそうなら、どうですか?そうでない場合、どのような代替方法を試すことができますか?

100
AGamePlayer

ファイルのグループをコピーしているのであれば、そうではありません。ディレクトリとその下のすべてのコンテンツをコピーする場合は、はい。このコマンドを考えると:

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

directoryHost~/the/targetに存在しない場合は、作成されます。ただし、~the/targetが存在しない場合は、問題が発生している可能性があります-このケースの正確な結果は覚えていませんが、意図したscpが失敗する準備をしてください。

39
John

私の知る限り、scp自体はそれを行うことはできません。ただし、ターゲットマシンにsshして、ディレクトリを作成してからコピーすることもできます。何かのようなもの:

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

ディレクトリ全体をコピーする場合は、上記は必要ありません。たとえば、ディレクトリ~/fooをリモートホストにコピーするには、-r(再帰的)フラグを使用できます。

scp ~/foo/ user@Host:~/

これにより、リモートホストにターゲットディレクトリ~/fooが作成されます。ただし、親ディレクトリを作成することはできません。ターゲットディレクトリbarが存在しない場合、scp ~/foo user@Host:~/bar/fooは失敗します。いずれの場合も、個々のファイルをコピーする場合、-rフラグはターゲットディレクトリの作成に役立ちません。

17
terdon

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

4
Stuart Cardall

はい、できます。 scpのmanページによると:

man scp

.....

-rディレクトリ全体を再帰的にコピーします。 scpは、ツリートラバーサルで検出されたシンボリックリンクをたどることに注意してください。

....

3
YoMismo

(rsshによって)sshが利用できないscpまたはsftpのみに制限されている場合、rsyncを使用して空のディレクトリツリーをコピーしてからファイルをコピーすることにより、ディレクトリを作成できます。

これが、ssh-copy-idが機能せず、.sshディレクトリが存在しない場合に、リモートホストに公開sshキーを配置する方法です。

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

ターゲットファイル名が同じである場合、このコマンドを1つのrsyncに組み合わせて、途中にもう1つインクルードフィルターを追加することができます。

1
user3132194

コマンドをmkdirコマンドと連鎖させて、作成したフォルダーを参照できます。

mkdir ~/new-folder/ && scp -P 22 <remote/url>:~/new-folder/
0
Ducky

「スマート」scp + ssh mkdirはどうですか?

これは、ターゲットディレクトリ階層を作成するスクリプトです1回のみディレクトリごと(ブラインドではないssh mkdir -p 毎回)。

根拠

ローカルディスク(イベント駆動型)に書き込まれるときにモーション記録(ビデオファイル)をコピーしています。

  • rsyncは、完全なディレクトリ比較を行う意味がないため、意味がありません。イベントごとに1つのファイルを転送しています。 rsyncを1つのサブディレクトリまたはファイルのみに制限すると、完全なターゲットディレクトリ階層を作成できなくなります。
  • scpはうまく機能しますが、ターゲットディレクトリが存在するかどうかはわかりません。また、すべてのファイルに対してssh mkdir -pを実行したくありません。

解決

  1. 初めて必要になったとき(最初にコピーするとき)に、sshを介して各ターゲットディレクトリを作成します。
  2. ターゲットdir名を配列にキャッシュして、ssh mkdir再び表示されるたびに。このアレイを毎日クリアして、巨大にならないようにします。
  3. ファイルをscpします。

コード例:

#!/bin/bash

TARGETHOST="some.hostname"
TARGETPATH="/data/backups/MOTION/"

ensure_dir() {
    if [ "$TODAY" != "$(date +%D)" ] ; then
        CREATED=()  # reset array daily and first time so it won't get huge
        TODAY=$(date +%D)
    fi  
    if [[ ! " ${CREATED[@]} " =~ " ${1} " ]]; then
        # create dir
        echo "Creating remote directory: $1"
        ssh $TARGETHOST "mkdir -p ${TARGETPATH}$1"
        CREATED+=("$1")
    fi  
}

# This line is specific to my use case, watching a directory for new files:
inotifywait -mr --format '%w %f' -e close_write --exclude '.jpg' /data/MOTION/ | while read filedir filename ; do
    RELDIR=$(echo $filedir | sed 's|/data/MOTION/||')
    ensure_dir "$RELDIR"
    echo "Copying '$filename' from '${filedir}' to '${RELDIR}'"
    scp -r -p "${filedir}${filename}" "${TARGETHOST}:${TARGETPATH}${RELDIR}${filename}"
done

「スマート」なmkdirの動作を示す一般的な出力:

Creating remote directory: 2019-12-28/movie-C6/
Copying 'test1.mp4' from '/data/MOTION/2019-12-28/movie-C6/' to '2019-12-28/movie-C6/'
Creating remote directory: 2019-12-28/movie-C4/
Copying '095700.mp4' from '/data/MOTION/2019-12-28/movie-C4/' to '2019-12-28/movie-C4/'
Copying '095841.mp4' from '/data/MOTION/2019-12-28/movie-C4/' to '2019-12-28/movie-C4/'
Copying '100410.mp4' from '/data/MOTION/2019-12-28/movie-C4/' to '2019-12-28/movie-C4/'
Creating remote directory: 2019-12-28/movie-C2/
Copying '102106.mp4' from '/data/MOTION/2019-12-28/movie-C2/' to '2019-12-28/movie-C2/'
Creating remote directory: 2019-12-28/movie-C5/
Copying '102318.mp4' from '/data/MOTION/2019-12-28/movie-C5/' to '2019-12-28/movie-C5/'
Copying '102326.mp4' from '/data/MOTION/2019-12-28/movie-C2/' to '2019-12-28/movie-C2/'
Creating remote directory: 2019-12-28/movie-C1/
Copying '102450.mp4' from '/data/MOTION/2019-12-28/movie-C1/' to '2019-12-28/movie-C1/'
Copying '102744.mp4' from '/data/MOTION/2019-12-28/movie-C2/' to '2019-12-28/movie-C2/'
Copying '103008.mp4' from '/data/MOTION/2019-12-28/movie-C2/' to '2019-12-28/movie-C2/'
Copying '103945.mp4' from '/data/MOTION/2019-12-28/movie-C6/' to '2019-12-28/movie-C6/'
Copying '104252.mp4' from '/data/MOTION/2019-12-28/movie-C6/' to '2019-12-28/movie-C6/'
Copying '104824.mp4' from '/data/MOTION/2019-12-28/movie-C6/' to '2019-12-28/movie-C6/'
0
Akom