ハードディスクにある特定のファイルのみ(様々なディレクトリに分散している)を
別のディレクトリに移したいということがあり、
以外に苦戦したのでここに方法を記載する。
やりたいこと
これを
こうしたい
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="*"で除外されないようにしたファイル以外を除外している
という処理のため、うまくいく。