指定された名前のディレクトリを繰り返しコピーします。

指定された名前のディレクトリを繰り返しコピーします。

ビルドされたディレクトリ構造の使用

#!/bin/bash
for name in A B
do
    mkdir -p /tmp/src/${name}/copyme
    echo "do not copy" > /tmp/src/${name}/no.txt
    echo "copy" > /tmp/src/${name}/copyme/yes.txt
done

copyme私はディレクトリとその中のファイルを/tmp/tgtにミラーリングしたいと思います。

これは簡単なはずです。rsyncコマンドラインオプションの順序を区別して、すべてを除いて関連パターンを含めます。しかし、

rsync -av --exclude='*' --include='copyme' /tmp/src/ /tmp/tgt/

すべての項目を除外します(ターゲットディレクトリのみを作成)。なぜ?

ベストアンサー1

実行すると、rsyncソースで見つかった名前をパターンと比較してテストし、最初に一致するパターンが適用されます。

$ rsync -avv --exclude='*' --include='copyme' /tmp/src/ /tmp/tgt/
sending incremental file list
[sender] hiding directory A because of pattern *
[sender] hiding directory B because of pattern *
delta-transmission disabled for local transfer or --whole-file
total: matches=0  hash_hits=0  false_alarms=0 data=0

sent 51 bytes  received 86 bytes  274.00 bytes/sec
total size is 0  speedup is 0.00

ディレクトリが除外されると(上記の「隠しディレクトリ...」を参照)、その内容は考慮されなくなります。除外パターンと埋め込みパターンを逆にすると、ディレクトリcopymeに到達しないため役に立ちません。

このマニュアルには次のようにrsync記載されています。

/foo/bar/bazたとえば、ディレクトリを含める場合/foo/foo/bar除外しないでください。これらの親ディレクトリの1つを除外すると、その内容を調べることはできません。これらのパスの再帰をブロックして埋め込みをrsync無効にします/foo/bar/bazrsyncディレクトリ階層のカットオフ部分にまったく表示されないコンテンツを一致させることは不可能です)。

だから代わりに:

$ rsync -avv --include='[AB]' --include='copyme/***' --exclude='*' /tmp/src/ /tmp/tgt/
sending incremental file list
[sender] showing directory A because of pattern [AB]
[sender] showing directory B because of pattern [AB]
[sender] showing directory A/copyme because of pattern copyme/***
[sender] hiding file A/no.txt because of pattern *
[sender] showing file A/copyme/yes.txt because of pattern copyme/***
[sender] showing directory B/copyme because of pattern copyme/***
[sender] hiding file B/no.txt because of pattern *
[sender] showing file B/copyme/yes.txt because of pattern copyme/***
created directory /tmp/tgt
delta-transmission disabled for local transfer or --whole-file
./
A/
A/copyme/
A/copyme/yes.txt
B/
B/copyme/
B/copyme/yes.txt
total: matches=0  hash_hits=0  false_alarms=0 data=10

sent 305 bytes  received 175 bytes  960.00 bytes/sec
total size is 10  speedup is 0.02

除外は包含の後に来るべきです。このcopyme/***パターンは、copymeディレクトリ名自体とその下のすべてのパス名と一致します。

Aディレクトリ名Bをハードコードしたくない場合は、次の手順を実行します。

for dir in /tmp/src/*; do
    [ ! -d "$dir" ] && continue
    rsync -avv --include="${dir##*/}" --include='copyme/***' --exclude='*' /tmp/src/ /tmp/tgt/
done

これは出力されます

sending incremental file list
[sender] showing directory A because of pattern A
[sender] hiding directory B because of pattern *
[sender] showing directory A/copyme because of pattern copyme/***
[sender] hiding file A/no.txt because of pattern *
[sender] showing file A/copyme/yes.txt because of pattern copyme/***
created directory /tmp/tgt
delta-transmission disabled for local transfer or --whole-file
./
A/
A/copyme/
A/copyme/yes.txt
total: matches=0  hash_hits=0  false_alarms=0 data=5

sent 180 bytes  received 148 bytes  656.00 bytes/sec
total size is 5  speedup is 0.02
sending incremental file list
[sender] hiding directory A because of pattern *
[sender] showing directory B because of pattern B
[sender] showing directory B/copyme because of pattern copyme/***
[sender] hiding file B/no.txt because of pattern *
[sender] showing file B/copyme/yes.txt because of pattern copyme/***
delta-transmission disabled for local transfer or --whole-file
B/
B/copyme/
B/copyme/yes.txt
total: matches=0  hash_hits=0  false_alarms=0 data=5

sent 180 bytes  received 117 bytes  594.00 bytes/sec
total size is 5  speedup is 0.02

結果は次のとおりです。

$ tree src tgt
src
|-- A
|   |-- copyme
|   |   `-- yes.txt
|   `-- no.txt
`-- B
    |-- copyme
    |   `-- yes.txt
    `-- no.txt

4 directories, 4 files
tgt
|-- A
|   `-- copyme
|       `-- yes.txt
`-- B
    `-- copyme
        `-- yes.txt

4 directories, 2 files

別のアプローチは、除外パターンまたはインクルードパターンを使用せずにrsyncディレクトリをfind見つけてコピーすることです。copymersync

find /tmp/src -type d -name 'copyme' -prune -exec sh -c '
    cd /tmp/src && rsync -aRvv "${1#/tmp/src/}/" /tmp/tgt/' sh {} ';'

-Rここで使用されている(--relative)フラグを参照してくださいrsync

sh -c見つかったディレクトリごとにcopyme実行されるスクリプトは、tocd操作を実行し、パス名/tmp/srcをコピーしてそのパス/tmp/srcの最初のビットを削除します。

-prune停止コマンドは、findすでに見つかったディレクトリ内で追加のfindディレクトリを検索します。copyme

おすすめ記事