3

私は3つのディレクトリを持っています。directory1とdirectory2を比較し、それらの変更/新しいファイルを取得して、directory3にコピーします。Linuxのdiffコマンドとcpコマンドを使用して、これを行う簡単な方法はありますか?私はアイデアを受け入れています。

ありがとう!

アンドリュー

4

5 に答える 5

1

向こうのスレッドはあなたの問題をかなりうまく解決してくれると思います!

そこからコピー:

#!/bin/bash

# setup folders for our different stages
DIST=/var/www/localhost/htdocs/dist/
DIST_OLD=/var/www/localhost/htdocs/dist_old/
DIST_UPGRADE=/var/www/localhost/htdocs/dist_upgrade/

cd $DIST

list=`find . -type f`

for a in $list; do
   if [ ! -f "$DIST_OLD$a" ]; then
        cp --parents $a $DIST_UPGRADE
      continue
   fi
   diff $a $DIST_OLD$a > /dev/null
   if [[ "$?" == "1" ]]; then
        # File exists but is different so copy changed file
        cp --parents $a $DIST_UPGRADE
   fi
done
于 2010-07-16T18:55:39.970 に答える
1

これがあなたの説明からあなたが望むものだと思います。

for file in dir2/*; do
    file_in_dir1=dir1/$(basename ${file})
    if [ ! -e  ${file_in_dir1} ]; then
        # If the file in dir2 does not exist in dir1, copy
        cp ${file} dir3
    elif ! diff ${file} ${file_in_dir1}; then
        # if the file in dir2 is different then the one in dir1, copy
        cp ${file} dir3
    fi
done

ファイルが dir1 には存在するが dir2 には存在しない場合に、何が必要かという点については、私が確信が持てませんでした。

于 2010-07-16T18:48:26.173 に答える
1

bash スクリプトなしで実行することもできます。

diff -qr ./dir1 ./dir2 | sed -e 's/^Only in\(.*\): \(.*\)/\1\/\2/g' -e 's/ and \..*differ$//g' -e 's/^Files //g' | xargs -I '{}' cp -Rf --parents '{}' ./dir3/

このソリューションでは、sed を使用して diff コマンドからすべての追加テキストを削除し、ディレクトリ構造を維持したままファイルをコピーします。

于 2013-08-01T23:52:08.617 に答える
0

以前に投稿された2つの回答は、私が始めるのに役立ちましたが、そこまでは行きませんでした。thomaxによって投稿されたソリューションは非常に近いものでしたが、osxのcpコマンドが--parentsパラメーターをサポートしていないという問題が発生したため、サブフォルダーの作成に関するロジックを追加する必要がありました。少し再構築します。これが私が最終的に得たものです:

#!/bin/bash

# setup folders for our different stages
DIST=/var/www/localhost/htdocs/dist/
DIST_OLD=/var/www/localhost/htdocs/dist_old/
DIST_UPGRADE=/var/www/localhost/htdocs/dist_upgrade/

cd $DIST

find . -type f | while read filename
do

    newfile=false
    modified=false
    if [ ! -e  "$DIST_OLD$filename" ]; then
        newfile=true
        echo "ADD $filename"
    elif ! cmp $filename $DIST_OLD$filename &>/dev/null; then
        modified=true
        echo "MOD $filename"
    fi

    if $newfile || $modified; then

        #massage the filepath to not include leading ./
        filepath=$DIST_UPGRADE$(echo $filename | cut -c3-)

        #create folder for it if it doesnt exist
        destfolder=$(echo $filepath | sed -e 's/\/[^\/]*$/\//')
        mkdir -p $destfolder

        #copy new/modified file to the upgrade folder
        cp $filename $filepath
    fi
done
于 2012-06-05T03:19:01.247 に答える
0

dir1があり、以下のようにコンテンツ セットアップと同じレベルにあるdir2と考えてください。dir3

    mkdir dir1
    mkdir dir2
    echo 1 > dir1/a
    echo 1 > dir2/a
    echo 2 > dir1/b
    echo 3 > dir2/b
    echo 4 > dir2/c
    cp -r dir1 dir3

次のようにパッチを作成して適用すると、次のようになります。

    diff -ruN dir1 dir2 | patch -p1 -d dir3

次に、コンテンツdir2dir3同等のものがあります。

dir2と同じレベルでない場合は、パッチ内のファイル名を編集して、とファイル名dir1 の両方に同じ量のパス コンポーネントが含まれるようにする必要があります。dir1dir2

これを行うためのエレガントな方法がないため (少なくとも私には知られています)、dir2を と同じレベルにすることをお勧めします。dir1

ここでは「醜い」方法に従ってください。

dir2あなたがいくつかの場所にあると考えてから、次のようにfromのパス$BASEDIR をトリムするために差分を更新する必要があります$BASEDIRdir2

    diff -ruN dir1 $BASEDIR/dir2 | \
    perl -slne 'BEGIN {$base =~ s/\//\\\//g; print $base}
                    s/\+\+\+ $base\//\+\+\+ /g; print'  \
    -- -base=$BASEDIR

そして、上記のように結果のパスを適用できます。

于 2013-01-08T08:58:27.307 に答える