ビルドされたディレクトリ構造の使用
#!/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/baz
(rsync
ディレクトリ階層のカットオフ部分にまったく表示されないコンテンツを一致させることは不可能です)。
だから代わりに:
$ 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
見つけてコピーすることです。copyme
rsync
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