Linux diffツール:変更されたファイルのリストを作成します


14

Linuxコマンドラインツールを使用してプログラムで変更されたファイルのリストを作成するにはどうすればよいですか?特定のファイル(デルタ、パッチ)の違いには興味がありません。以前の製品リリースと比較した新しいファイルまたは変更されたファイルのリストが必要です。新しい製品の更新を公開できるように。

更新:diff -qr非常に便利な出力を生成しません。の出力diff -qrも処理する必要があります。より良い方法はありますか?


「便利な」出力の例は何ですか?
-frogstarr78

回答:


8

これには簡単なアプローチがあります:rsync-previewモードを使用します:

rsync -aHSvn --delete old_dir/ new-dir/

そのコマンドによって「削除される」と表示されるファイルは、「新しい」ファイルになります。転送される他のものは何らかの方法で変更されています。詳細については、rsync-man-pageを参照してください。


13

diffツールを使用できます。オプション-qおよび-rを参照してください。

-q  --brief
Output only whether files differ.

-r  --recursive
Recursively compare any subdirectories found.

例:

diff -qr dir1 dir2

Only inディレクトリが理想的なコピーであっても、それが表示されるという意味のない情報で散らばっている、まったくひどく読みにくい出力です。変更を古いリビジョンと比較し、リビジョン全体を別のディレクトリにダウンロードし、標準のSVNツールを使用して比較する必要がありました。それが唯一の方法のように思えます…
ハイエンジェル

3

diffutilsパッケージには、lsdiffツールを。の出力diff -uをlsdiffに渡すだけです:

diff -u --other-diff-options path1 path2 | lsdiff

良い提案、ありがとう。patchutils私のパッケージに含まれていました(CentOS 5.x)。
スティーブケレット

うん、Ubuntu / Debian用のpatchutilsパッケージも。
artfulrobot

1

各更新時にファイルに触れるだけで、それ以降に変更されたファイルを見つけることができます find /tree/location -newer /last/update/file -print


1

変更されたファイルの名前のみを取得するには、次のコマンドを使用します。

diff -r dirt1 dir2 --brief | sed 's/^Only in \([^:]*\): /\1\//' | sed 's/^Files \(.*\) and .* differ/\1/'

一部のファイルをオブジェクトファイルまたはライブラリファイルとして除外する必要がある場合は、次を使用できます。

diff -r dirt1 dir2 --brief --exclude "*.o" --exclude "*.a" | sed 's/^Only in \([^:]*\): /\1\//' | sed 's/^Files \(.*\) and .* differ/\1/'

1

プログラムで新しいファイルまたは変更されたファイルのリストを作成するには、rsyncsort、およびuniqを使用するのが最善の解決策です。

(rsync -rcn --out-format="%n" old/ new/ && rsync -rcn --out-format="%n" new/ old/) | sort | uniq

この例を使用して説明します。2つのdokuwikiリリースを比較して、変更されたファイルと新しく作成されたファイルを確認します。

私たちは、wgetコマンドでタールを取得したディレクトリにそれらを抽出old/してnew/

wget http://download.dokuwiki.org/src/dokuwiki/dokuwiki-2014-09-29d.tgz
wget http://download.dokuwiki.org/src/dokuwiki/dokuwiki-2014-09-29.tgz
mkdir old && tar xzf dokuwiki-2014-09-29.tgz -C old --strip-components=1
mkdir new && tar xzf dokuwiki-2014-09-29d.tgz -C new --strip-components=1

rsyncとdiffの比較がここに示されているように、rsyncを一方向に実行すると、新しく作成されたファイルを見逃す可能性があります。

rsync -rcn --out-format="%n" old/ new/

次の出力が生成されます。

VERSION
doku.php
conf/mime.conf
inc/auth.php
inc/lang/no/lang.php
lib/plugins/acl/remote.php
lib/plugins/authplain/auth.php
lib/plugins/usermanager/admin.php

一方向でのみrsyncを実行すると、新しく作成されたファイルが失われ、逆の方法では削除されたファイルが失われます。diffの出力を比較してください。

diff -qr old/ new/

次の出力が生成されます。

Files old/VERSION and new/VERSION differ
Files old/conf/mime.conf and new/conf/mime.conf differ
Only in new/data/pages: playground
Files old/doku.php and new/doku.php differ
Files old/inc/auth.php and new/inc/auth.php differ
Files old/inc/lang/no/lang.php and new/inc/lang/no/lang.php differ
Files old/lib/plugins/acl/remote.php and new/lib/plugins/acl/remote.php differ
Files old/lib/plugins/authplain/auth.php and new/lib/plugins/authplain/auth.php differ
Files old/lib/plugins/usermanager/admin.php and new/lib/plugins/usermanager/admin.php differ

両方の方法でrsyncを実行し、出力をソートして重複を削除するdata/pages/playground/と、data/pages/playground/playground.txt最初にディレクトリとファイルが失われたことがわかります。

(rsync -rcn --out-format="%n" old/ new/ && rsync -rcn --out-format="%n" new/ old/) | sort | uniq

次の出力が生成されます。

VERSION
conf/mime.conf
data/pages/playground/
data/pages/playground/playground.txt
doku.php
inc/auth.php
inc/lang/no/lang.php
lib/plugins/acl/remote.php
lib/plugins/authplain/auth.php
lib/plugins/usermanager/admin.php

rsync これらの引数で実行されます:

  • -r 「ディレクトリに再帰する」、
  • -c 同じサイズのファイルを比較し、「mod-timeとサイズではなく、チェックサムに基づいてスキップする」だけで、
  • -n 「変更を加えずに試運転を実行する」
  • --out-format="%n" 「指定されたFORMATを使用して更新を出力する」、これはファイル名のみの「%n」です

の出力(ファイルのリスト)はrsync、を使用して結合およびソートされsort、このソートされたリストは、uniq



0

これはトリックをするかもしれません:

compare_dirs()
{
    # Shows which files and directories exist in one directory but not both
    if [ $# -ne 2 ]
    then
        echo "Usage: compare_dirs dir1 dir2" >&2
        return 2
    fi
    for path
    do
        if [ ! -d "$path" ]
        then
            echo "Not a directory: $path" >&2
            return 1
        fi
    done
    comm -3 \
        <(cd -- "$1" && find . -printf '%P\0' | sort -z | quote_shell) \
        <(cd -- "$2" && find . -printf '%P\0' | sort -z | quote_shell)
}

0

通常、ファイルをSubVersionやgitなどの何らかのバージョン管理システムに配置します。これらはすぐに使用できるためです。

ただし、dir1でforループを使用して簡単なスクリプトを実行し、すべてのファイルをdir2のファイルと比較できます。forループは、diffからの終了コードを調べて、ファイルが異なっていたかどうかを知ることができます。

たぶんこのようなもの:

for f in `(cd dir1 ; find .)`
do 
  diff $f ../dir2/$f
  if [ "$?" == "0" ]
  then 
    echo same
  else 
    echo diff: $f
  fi
done

注:スクリプトはテストされていないため、上記の例は「bashに触発された擬似コード」です...


もう一度行ってみましょう。ただしgitを使用します

プレイするサンプルファイルを作成します

mkdir -p dir1/test1/test11
mkdir -p dir1/test1/test12
mkdir -p dir1/test1/test13
echo "Test1" >> dir1/test1/test11/t1.txt
echo "Test2" >> dir1/test1/test12/t2.txt
echo "Test3" >> dir1/test1/test13/t3.txt

#And a dir to work in
mkdir gitdir

次に、dirを入力してdir1をインポートします

cd gitdir/
git init .
cp -r ../dir1/* .
git add .
git commit -m 'dir1'

外に出てdir1を変更します(したがって、dir1になります)

cd ..
echo "Test2" > dir1/test1/test11/t1.txt

次に、git dirに移動して、新しいディレクトリをインポートします

cd gitdir/
cp -r ../dir1/* .

次に、何が変更されたかをgitに尋ねます(statusコマンドを使用)

git status -s

出力は、次のような変更を含むリストです。

 M test1/test11/t1.txt

0

たぶん、あなたは別の何かで幸せになるでしょう。試してくださいgit

例としてこれを実行します。

mkdir a
cd a
git init
touch b
git add . && git commit -m "Empty file"
git status
echo c >> b
git status
git add . && git commit -m "Full file"
git status

gitファイルを追跡します。このコマンドgit statusは、最後のコミット以降に変更されたすべてのファイルを表示します。


0

これはrsyncに似ています:宛先の新しいファイルがいつ上書きされるかを示します(後で確認されますが、重複はありません)。

質問で示されているように、「diff -q -r」を使用するには、何らかの処理が必要になる場合があります。質問では、出力の形式を指定しませんでした。回答はさまざまな種類のレポートを提供します。

rsyncこれは、に比べてはるかに高速であるため、この目的に役立つツールですdiff。ただし、@ nilsが提案するソリューションは、古いディレクトリツリーと新しいディレクトリツリーの実際の違いよりもはるかに冗長です(そして、より多くのファイルをリストします)。たとえば、それをその回答用に書いたスクリプトと比較し、同じデータで実行すると、

  • @nilsの回答は605行を生成します(ディレクトリの変更が含まれているためです)。
  • 「diff -q -r」は、数分間実行した後に352行を生成します。
  • 私のスクリプトは252行を示しています(実際のファイルは変更、追加、削除されています)

新しいファイルをdiff適切に説明するには、オプションも必要です(提案された回答には表示されません)。ただし、これはに比べてはるかに遅い(桁違い)ので、後者の出力を改善する方法があります。-Nrsync

参考文献


0

私はずっとsha1sum(またはmd5sumでさえ、このコンテキストでは非常に安全です)に常にこだわりました。

find . -type f -print0 | xargs -0 md5sum | sort -k2 > /tmp/before
# don't miss the "sort" in there; it's important

# (later)
find . -type f -print0 | xargs -0 md5sum | sort -k2 > /tmp/after
vimdiff /tmp/before /tmp/after
# or whatever diff tool you like, even "diff -u"

名前を変更したり移動したりするファイルが多すぎる場合のように、最初のフィールドでソートしてからdiffを実行すると役立つ場合がありますが、ほとんどの場合これで十分です。

他の方法のいくつかと比較して、これには「以前の」ファイルのコピーを保持する必要がないという利点があることに注意してください。md5sum出力ファイルのみ。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.