ハードディスクにある特定のファイルのみ(様々なディレクトリに分散している)を
別のディレクトリに移したいということがあり、
以外に苦戦したのでここに方法を記載する。
やりたいこと
これを
こうしたい
rsync
単純にファイルのコピーだけならscp
でもいいが、ファイルの所有者やタイムスタンプなども保持したまま
コピーするなら、rsync
を使う。
exclude
オプション
Usage : exclude="PATTERN"
そのパターンにマッチするファイル、ディレクトリを除外する。
(*,??)などのワイルドカード指定も可。
rsync -avPh --exclude="*.mp3" dir1/ dir2/
これで、dir1/の中にある.mp3
ファイル以外のファイルがコピー(同期)される。
include
オプション
Usage : include="PATTERN"
そのパターンにマッチするファイル、ディレクトリを除外させない。
*,??
などのワイルドカード指定も可。
しかし、
rsync -avPh --include="*.mp3" dir1/ dir2/
とすると、dir1/の中にある.mp3
ファイルのみがコピーされるのではなく、
dir1/のなかのファイルが全てコピーされてしまう。
さらに直下のディレクトリのみしか判定しなかったりと、思ったとおりに動かない。
include
はexclude
と併用する
はじめに正解を書くと、
rsync -avPh --include="/*" --include="*.mp3" --exclude="*" dir1/ dir2/
となる。
一つずつオプションの解説をする。
-
--include="/*"
- 現ディレクトリだけでなく、子ディレクトリ(それより深いディレクトリも含め)対象とする
-
--include="*.mp3"
- コピーしたいファイルのパターンを指定。(今回は
mp3
)
- コピーしたいファイルのパターンを指定。(今回は
-
--exclude="*"
-
include
しているもの以外を除外する
-
また、--include="*.mp3 --include="*.wav"
などとすることで複数のパターンでも指定できる。
FYI include
,exclude
には順序がある。
rsync -avPh --exclude="*" --include="/*" --include="*.mp3" dir1/ dir2/
とすると、何もコピーされない。
これは、include
,exclude
には先頭から順に適用されるという特性があるためである。
--include="/*"
は、除外させないというオプションであり、上の例だと、
1. exclude="*"
で全てを除外
2. include
したいけどなにもない
3. 以下同様
という処理になっている。
正解の例だと
(rsync -avPh --include="/*" --include="*.mp3" --exclude="*" dir1/ dir2/
)、
-
include="/*"
で子ディレクトリ以下も対象にし、 -
include="*.mp3"
で.mp3ファイルは除外されないようにしてから、 -
exclude="*"
で除外されないようにしたファイル以外を除外している
という処理のため、うまくいく。