2つのディレクトリをrsyncで比較し、違いのみを出力することは可能ですか?模擬オプションがありますが、詳細度を特定のレベルに上げると、比較されたすべてのファイルが表示されます。
ls -alR
とdiff
はここではオプションではありません。ソースにハードリンクがあり、すべての行が異なるためです。 (もちろん、この列はPerlで削除できます。)
おそらく、双方向でrsync -avun --delete
のようなものを実行する必要があります。
しかし、実際に何を達成しようとしていますか?
更新:
rsync -avun --delete $TARGET $SOURCE |grep "^deleting "
は、ターゲットディレクトリに存在しないファイルのリストを提供します。
"grep delet"各行が出力されるため:delet ing ..file ..
rsync -avun $SOURCE $TARGET
は、「異なる」ファイル(新しいファイルを含む)のリストを提供します。
Nilsの回答に追加するため(Google経由でこれに遭遇した人のために)、デフォルトではrsync
はファイルサイズと変更時間のみを比較して、違いがあるかどうかを判断します。 (それらが異なる場合、より多くのことを行いますが、同じである場合、そこで停止します。)
実際のファイルcontentsを比較する場合は、同じサイズで最終変更時刻のファイルでも、フラグ-c
を追加してrsync
にファイルを比較するように指示しますチェックサム。
rsync -avnc $SOURCE $TARGET
(-u
オプションは、$TARGET
よりも$SOURCE
の方が新しいファイルを無視するようにrsyncに指示します。これは、内容を比較している場合はおそらく不要です。)
rsync
にあまり詳しくない人のために:
rsync -rvnc --delete ${SOURCE}/ ${DEST}
-n
:最も重要なビット-実行not何かを変更;-rc
:内容のみを比較します(それ以外の場合は-ac
を使用します);-v
:ファイルを一覧表示します)--delete
:単方向の違いではなく、対称的な違いを探します。/
は、「ディレクトリ内を見て、そのcontentsを宛先と比較する」ことを意味します。通常の
rsync
出力を出力します、
${SOURCE}
のすべての「新しい」ファイルの行に1つの<filename>
${DEST}
の「新しい」ファイルごとに1つの"deleting <filename>"行。また、シンボリックリンクに対して"通常でないファイル<filename>"のようないくつかの警告を出力する場合もあります。
PS。私はそれがひどいPSであることを知っています-それは確かにラッシュで追加されました。それにもかかわらず、私はこれが便利だと思うかもしれません。
find $SOURCE -type f -exec md5sum {} \; | tee source.md5
find $DEST -type f -exec md5sum {} \; | tee dest.md5
ファイル名に改行が含まれていない場合は、*.md5
ファイルとdiff
の両方を並べ替えることができます。 (ただし、これはファイルに対してのみ機能します。つまり、どちらかの側の空のディレクトリは検出されません。)
驚くべきことに、6年間で-i
オプションを使用したり、Nice出力を提供したりする答えはないので、ここで説明します。
rsync -rin --ignore-existing "$LEFT_DIR"/ "$RIGHT_DIR"/|sed -e 's/^[^ ]* /L /'
rsync -rin --ignore-existing "$RIGHT_DIR"/ "$LEFT_DIR"/|sed -e 's/^[^ ]* /R /'
rsync -rin --existing "$LEFT_DIR"/ "$RIGHT_DIR"/|sed -e 's/^/X /'
次に出力の例を示します。
L file-only-in-Left-dir
R file-only-in-right-dir
X >f.st...... file-with-dif-size-and-time
X .f...p..... file-with-dif-perms
各行の最初の文字に注意してください:
L
/R
は、ファイル/ディレクトリがL
eftまたはR
ightディレクトリにのみ表示されることを意味します。X
は、ファイルが両面に表示されるが同じではないことを意味します(この場合、次の11文字で詳細がわかります。s
、t
およびp
s ize、t ime、およびp ermissionsの違いをそれぞれ示します-詳細については、man rsync
を試して--itemize-changes
を検索してください)。ファイルの所有者/グループ/権限も比較する場合は、オプション-o
/-g
/-p
をそれぞれ追加します。最後に、デフォルトでは、rsyncは2つのファイルが同じ名前、時間、サイズである場合、それらを同じと見なします。これは非常に高速で、ほとんどの場合は十分以上ですが、100%になりたい場合は、-c
を追加して、同じ名前、時間、サイズのファイルの内容も比較してください。
ここにあります。このように呼ぶ
diff-dirs Left_Dir Right_Dir [options]
上記の「使用したい追加オプション」で説明したすべてのオプションがここでも適用されます。
#!/bin/bash
# Compare two directories using rsync and print the differences
# CAUTION: options MUST appear after the directories
#
# SYNTAX
#---------
# diff-dirs Left_Dir Right_Dir [options]
#
# EXAMPLE OF OUTPUT
#------------------
# L file-only-in-Left-dir
# R file-only-in-right-dir
# X >f.st...... file-with-dif-size-and-time
# X .f...p..... file-with-dif-perms
#
# L / R mean that the file/dir appears only at the `L`eft or `R`ight dir.
#
# X means that a file appears on both sides but is not the same (in which
# case the next 11 characters give you more info. In most cases knowing
# that s,t,T and p depict differences in Size, Time and Permissions
# is enough but `man rsync` has more info
# (look at the --itemize-changes option)
#
# OPTIONS
#---------
# All options are passed to rsync. Here are the most useful for the purpose
# of directory comparisons:
#
# -c will force comparison of file contents (otherwise only
# time & size is compared which is much faster)
#
# -p/-o/-g will force comparison of permissions/owner/group
if [[ -z $2 ]] ; then
echo "USAGE: $0 dir1 dir2 [optional rsync arguments]"
exit 1
fi
set -e
LEFT_DIR=$1; shift
RIGHT_DIR=$1; shift
OPTIONS="$*"
# Files that don't exist in Right_Dir
rsync $OPTIONS -rin --ignore-existing "$LEFT_DIR"/ "$RIGHT_DIR"/|sed -e 's/^[^ ]* /L /'
# Files that don't exist in Left_Dir
rsync $OPTIONS -rin --ignore-existing "$RIGHT_DIR"/ "$LEFT_DIR"/|sed -e 's/^[^ ]* /R /'
# Files that exist in both dirs but have differences
rsync $OPTIONS -rin --existing "$LEFT_DIR"/ "$RIGHT_DIR"/|sed -e 's/^/X /'
次のようにrsyncを呼び出します。
rsync -rin ...
-i
(--itemize-changes
)を使用して、2つのディレクトリの違いに関する情報を含むすべてのファイルの出力を1行出力するようにrsyncに指示します。 rsyncの通常の動作を抑制するために-n
が必要です(ファイルをコピー/削除して2つのディレクトリを同期しようとします)。また、すべてのファイル/サブディレクトリに対して-r
を再帰的に動作させる必要があります。
Rsyncを3回呼び出します。
1回目の呼び出し:Dir_Bに存在しないファイルを印刷します。両側に存在するファイルを無視するには、--ignore-existing
を使用する必要があります。
rsync -rin --ignore-existing $DIR_A/ $DIR_B/
2回目の呼び出し:まったく同じですが、DIR_A/DIR_Bの順序を入れ替えます。
回目の呼び出し:最後に、--existing
を使用して、両方のディレクトリに表示されるファイルのみをチェックします。
rsync -rin --existing $DIR_A/ $DIR_B/
あなたの質問から、diff on lsを使用したくないことを理解していますが、ディレクトリでdiffを再帰的に使用することもできます。
diff -rq DIR1 DIR2
これを機能させるために数回の試行が必要でした。ジョージの説明によると、Nilsの回答では、$TARGET
が末尾の/
で終わる必要があります。
これは、末尾に/
を明示的に追加するバージョンです。
rsync -avun --delete ${TARGET}/ ${SOURCE} | sed -ne 's/^deleting *//p'
これにより、${SOURCE}
ディレクトリの下には存在するが、${TARGET}
ディレクトリの下には存在しないファイルのリストが表示されます。
ここではsed
を使用して、出力行から先頭のdeleting
を削除し、それらの行のみを出力しています。
rsync
オプション-c
は使用していません。これは、ファイルの内容を比較すると、ユースケースがはるかに遅くなり、ファイルサイズと変更時間のみを比較することも、これらのケースでは十分に思えるからです。私のコンピュータがクロックスキューの問題に苦しんでいるか、何かが悪意を持ってタイムスタンプを変更したと疑う理由はありません。また、-c
の結果は、ファイルを削除する決定を変更することはできません。ファイルを更新または保持する決定のみを変更できます。
また、-u
と-a
を使用して(-r
ではなく)、後でコマンドラインを再利用して、選択したディレクトリとファイルを${SOURCE}
からコピーするように変更できるようにしています次のように${TARGET}
に:
rsync -avu ${SOURCE}/{dirA,dirB,fileX} ${TARGET} # copy some files
これを行う別のアイデアがあります:
rsync -rn --out-format=FILEDETAIL::%n $TARGET $SOURCE | grep "^FILEDETAIL"
「FILEDETAIL ::」をコマンドの出力と一致させることができます。また、文字列「FILEDETAIL ::」を変更できます。 「%n」はファイル名です。
rsync
manpage で述べたように:
-r, --recursive recurse into directories -n, --dry-run perform a trial run with no changes made