Сравните 2 каталога и скопируйте различия в каталог 3 - PullRequest
3 голосов
/ 16 июля 2010

У меня есть три каталога.Я хотел бы сравнить каталог1 с каталогом2, затем взять эти изменения / новые файлы и скопировать их в каталог3.Есть ли простой способ сделать это, возможно, с помощью команд linux diff и cp?Я открыт для идей.

Спасибо!

Андрей

Ответы [ 5 ]

1 голос
/ 02 августа 2013

Вы также можете сделать это без 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/

Это решение удаляет весь дополнительный текст из команды diff с помощью sed, а затем копирует файлы, сохраняя структуру каталогов.

1 голос
/ 16 июля 2010

Тема там решает вашу проблему довольно хорошо, я должен подумать!

Скопировано оттуда:

#!/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
1 голос
/ 16 июля 2010

Я полагаю, что это то, что вы хотите от своего описания.

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.

0 голосов
/ 08 января 2013

Предположим, у вас есть 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

Тогда у вас есть содержимое dir2 и dir3 эквивалент.

Если ваш dir2 не на том же уровне, что и dir1 тогда вы должны редактировать имена файлов в патче так что у вас есть равное количество компонентов пути в именах файлов dir1 и dir2.

Вам лучше поставить dir2 на тот же уровень, что и dir1, потому что нет элегантного способа сделать это (по крайней мере, мне известно).

Здесь следуйте "уродливым" путем.

Считайте, что ваш dir2 находится в каком-то $BASEDIR тогда вы должны обновить ваш diff, чтобы урезать путь $BASEDIR из dir2 как это

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

И тогда вы можете применить полученный путь, как указано выше.

0 голосов
/ 05 июня 2012

Два ранее опубликованных ответа помогли мне начать, но не помогли мне в этом.Решение, опубликованное thomax, было действительно близко, но я столкнулся с проблемой, когда команда cp на osx не поддерживает параметр --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
...