同様のディレクトリツリーの同じ場所間で自動的にコピー

同様のディレクトリツリーの同じ場所間で自動的にコピー

私は2台のコンピュータに大きなファイルシステムツリーを維持しており、多くの場合、あるコンピュータから別のコンピュータに1つまたは複数のファイルをコピーする必要があります。

長く同じパスを入力しなくても、2つのツリーの同じ場所間で自動的にコピーできますか?


たとえば、を指定せずにmyroot/a/b/cファイルをコピーしたいとします。remoteroot/a/b/ca/b/c

このような:

myroot/a/b/c$: smartcopy myfile --destination-root remoteroot

ベストアンサー1

ユーティリティrsync-Rオプションはある程度役に立ちますが、次の手順を実行する必要があります。みんなソースパスそしてrsync「ルート」部分と見なすソースパスの部分を示します。./この情報をソースパスの任意の場所に挿入して提供できます。

あなたの例では、「ルート」部分は正しいので、myroot/コマンドは次のようになります。

myroot/a/b/c$ rsync -R myroot/./a/b/c/myfile remoteroot

複雑な状況では、現在のディレクトリパスの外側に「ルート」部分を指定する簡単な方法が欲しいとします。

強力で比較的簡単な方法は、パス深度数を使用することです。たとえば、bash次のことができます。

/path/to/myroot/a/b/c$ rsync -R "$(idx=4; IFS=/; set -- $PWD ; printf '%s/' "${@:1:idx}" . "${@:idx+1}")"/myfile remoteroot
                                 #     ^--- 4th piece of path counted as number of slashes in $PWD

もちろん、簡単な説明ではありませんが、コマンドの置き換えは次のようにファイル内の関数になること.bashrcができます。

rootidx() {
    local idx="$1"

    # make Bash perform Word Splitting on / character
    local IFS=/ # make IFS local here, so to not affect global IFS

    # set function's arguments to each piece of current directory path,
    # as split on $IFS
    set -- $PWD

    # print from first argument up to the one indicated by wanted index,
    # then a ./, then from wanted index onwards
    printf '%s/' "${@:1:idx}" . "${@:idx+1}"
}

使用法は次のとおりです。

/path/to/myroot/a/b/c$ rsync -R "$(rootidx 4)"/myfile remoteroot

または、「ルート」を指定された位置に配置します。ひもフルパスの場合、単純でPOSIX互換方式は次のとおりです。

/path/to/myroot/a/b/c$ rsync -R "${PWD%%/myroot/*}/myroot/./${PWD#*/myroot/}"/myfile remoteroot

パラメータ拡張を使用して、$PWD現在のディレクトリパスに最初に表示される文字列を挿入します./myroot

ただし、パラメーターの拡張は非常に簡単ですが、パラメーターを指定するときは注意が必要です。一致する中間体それ以外の場合、この特定の拡張は期待どおりに機能せず、代わりに現在のディレクトリ全体をそれ自体とその間に指定された文字列に関連付けます。

このパラメータ拡張は関数として作成することもできます。これは関数をより強力にするのに役立ちます。たとえば、次のようになります。

rootname() {
    [[ "$PWD" == */"$1"/* ]] && \  # check presence of string as intermediate path
        printf '%s' "${PWD%%/${1}/*}/${1}/./${PWD#*/${1}/}" || \  # apply the injection, or
        printf '%s -not valid-' "$1"   # try to produce an unlikely filename so to make `rsync` fail
}

使用法は次のとおりです。

/path/to/myroot/a/b/c$ rsync -R "$(rootname myroot)"/myfile remoteroot

最後に、パス名の拡張を理解するGNUツールとシェルがある場合は、**ローカルコピー操作にこれらの機能を使用することもできますcp。たとえば、

/path/to/myroot/a/b/c$ (shopt -s globstar; cd "$(rootidx 4)" && cp --parents **/myfile otherpath)

このshopt -s globstarコマンドはbash拡張を有効にします**

もちろん、それを関数に変換することもできます。

smartcp() {
    # FIXME: some sanity checks over arguments here
    # TODO: detect type of first argument, and use either rootidx or rootname accordingly
    (shopt -s globstar; cd "$(rootidx "$1")" && cp --parents **/"${2}" "$3")
}

だから:

/path/to/myroot/a/b/c$ smartcp 4 myfile otherpath

おすすめ記事