разница между двумя каталогами в linux

<p>я пытаюсь найти файлы, существующие в одном каталоге, но не в другом, я пытался использовать эту команду:</p><pre><code>diff -q dir1 dir2 </code></pre><p>проблема с приведенной выше командой в том, что она находит оба файла в <code>dir1</code>, но не в <code>dir2</code>, а также файлы в <code>dir2</code>, но не в <code>dir1</code>, </p><p>я пытаюсь найти файлы в <code>dir1</code>, но не только в <code>dir2</code>.</p><p>вот небольшой пример того, как выглядят мои данные</p><pre><code>dir1 dir2 dir3 1.txt 1.txt 1.txt 2.txt 3.txt 3.txt 5.txt 4.txt 5.txt 6.txt 7.txt 8.txt </code></pre><p>другой вопрос, который у меня возникает, - как найти файлы в <code>dir1</code>, а не в <code>dir2</code> или <code>dir3</code> в одной команде?</p>

<pre><code>diff -r dir1 dir2 | grep dir1 | awk '{print $4}' > difference1.txt <strong> объяснение: </strong> diff -r dir1 dir2 показывает, какие файлы находятся только в dir1 и только в dir2, а также изменения файлов, присутствующих в обоих каталогах, если таковые имеются. diff -r dir1 dir2 | grep dir1 показывает, какие файлы есть только в dir1 awk для печати только имени файла. 

это должно сделать работу:diff -rq dir1 dir2 опции объяснены (через diff (1) <a href="https://linux.die.net/man/1/diff">справочная страница ): -r - рекурсивно сравнивать любые найденные подкаталоги. -q - выводить только те файлы, которые отличаются. 

comm -23 <(ls dir1 |sort) <(ls dir2|sort) эта команда выдаст вам файлы, которые находятся в dir1 и не в dir2.что касается знака <( ), вы можете использовать его как «процесс замены».

хороший способ сделать это сравнение - использовать find с md5sum, а затем diff.пример:используйте find для вывода списка всех файлов в каталоге, затем вычислите хэш md5 для каждого файла и передайте его в файл:find /dir1/ -type f -exec md5sum {} ; > dir1.txt проделайте ту же процедуру с другим каталогом:find /dir2/ -type f -exec md5sum {} ; > dir2.txt затем сравните результат двух файлов с «diff»:diff dir1.txt dir2.txt эта стратегия очень полезна, когда сравниваемые два каталога не находятся на одном компьютере, и вам необходимо убедиться, что файлы в обоих каталогах совпадают.еще один хороший способ сделать это - использовать<strong> git </strong>git diff --no-index dir1/ dir2/ с наилучшими пожеланиями!

мелд ( <a href="http://meldmerge.org/">http://meldmerge.org/ ) отлично справляется со сравнением каталогов и файлов внутри. <a href="https://i.stack.imgur.com/ksnmd.png"> <img src="https://i.stack.imgur.com/ksnmd.png" alt="meld comparing directories">  

vim's <a href="http://www.vim.org/scripts/script.php?script_id=102">dirdiff plugin - еще один очень полезный инструмент для сравнения каталогов.vim -c "dirdiff dir1 dir2" он не только перечисляет, какие файлы различаются между каталогами, но также позволяет вам проверять/изменять с помощью vimdiff файлы, которые отличаются.

неудовлетворенный всеми ответами, так как большинство из них работают очень медленно и выдают излишне длинный вывод для больших каталогов, я написал свой собственный скрипт на python для сравнения двух папок.в отличие от многих других решений, он не сравнивает содержимое файлов. также это не входит в подкаталоги, которые отсутствуют в другом каталоге. таким образом, вывод довольно лаконичен, и скрипт работает быстро.#!/usr/bin/env python3 import os, sys def compare_dirs(d1: "old directory name", d2: "new directory name"): def print_local(a, msg): print('dir ' if a[2] else 'file', a[1], msg) # ensure validity for d in [d1,d2]: if not os.path.isdir(d): raise valueerror("not a directory: " + d) # get relative path l1 = [(x,os.path.join(d1,x)) for x in os.listdir(d1)] l2 = [(x,os.path.join(d2,x)) for x in os.listdir(d2)] # determine type: directory or file? l1 = sorted([(x,y,os.path.isdir(y)) for x,y in l1]) l2 = sorted([(x,y,os.path.isdir(y)) for x,y in l2]) i1 = i2 = 0 common_dirs = [] while i1<len(l1) and i2<len(l2): if l1[i1][0] == l2[i2][0]: # same name if l1[i1][2] == l2[i2][2]: # same type if l1[i1][2]: # remember this folder for recursion common_dirs.append((l1[i1][1], l2[i2][1])) else: print_local(l1[i1],'type changed') i1 += 1 i2 += 1 elif l1[i1][0]<l2[i2][0]: print_local(l1[i1],'removed') i1 += 1 elif l1[i1][0]>l2[i2][0]: print_local(l2[i2],'added') i2 += 1 while i1<len(l1): print_local(l1[i1],'removed') i1 += 1 while i2<len(l2): print_local(l2[i2],'added') i2 += 1 # compare subfolders recursively for sd1,sd2 in common_dirs: compare_dirs(sd1, sd2) if __name__=="__main__": compare_dirs(sys.argv[1], sys.argv[2]) пример использования:user@laptop:~$ python3 compare\_dirs.py dir1/ dir2/ dir dir1/out/flavor-domino removed dir dir2/out/flavor-maxim2 added dir dir1/target/vendor/flavor-domino removed dir dir2/target/vendor/flavor-maxim2 added file dir1/tmp/.kconfig-flavor\_domino removed file dir2/tmp/.kconfig-flavor\_maxim2 added dir dir2/tools/tools/livesuit\_for\_linux64 added </code></pre><p>или, если вы хотите видеть только файлы из первого каталога: </p><pre><code>user@laptop:~$ python3 compare_dirs.py dir2/ dir1/ | grep dir1 dir dir1/out/flavor-domino added dir dir1/target/vendor/flavor-domino added file dir1/tmp/.kconfig-flavor_domino added постскриптум если вам нужно сравнить размеры файлов и хэши файлов на предмет возможных изменений, я опубликовал обновленный скрипт здесь: <a href="https://gist.github.com/amakukha/f489cbde2afd32817f8e866cf4abe779">https://gist.github.com/amakukha/f489cbde2afd32817f8e866cf4abe779 

другой (может быть, быстрее для больших каталогов) подход:$ find dir1 | sed 's,^[^/]*/,,' | sort > dir1.txt && find dir2 | sed 's,^[^/]*/,,' | sort > dir2.txt $ diff dir1.txt dir2.txt команда sed удаляет первый компонент каталога <a href="https://stackoverflow.com/a/5312007/761131">благодаря посту эрика )

это немного поздно, но может кому-то помочь. не уверен, что diff или rsync выкладывают только имена файлов в таком формате. спасибо plhn за то, что дали то хорошее решение, которое я расширил ниже.если вам нужны только имена файлов, поэтому легко скопировать нужные файлы в чистом формате, вы можете использовать команду find.comm -23 <(find dir1 | sed 's/dir1///'| sort) <(find dir2 | sed 's/dir2///'| sort) | sed 's/^//dir1/' это предполагает, что и dir1, и dir2 находятся в одной родительской папке. sed просто удаляет родительскую папку, чтобы вы могли сравнить яблоки с яблоками. последний sed просто возвращает имя dir1.если вы просто хотите файлы:comm -23 <(find dir1 -type f | sed 's/dir1///'| sort) <(find dir2 -type f | sed 's/dir2///'| sort) | sed 's/^//dir1/' аналогично для каталогов:comm -23 <(find dir1 -type d | sed 's/dir1///'| sort) <(find dir2 -type d | sed 's/dir2///'| sort) | sed 's/^//dir1/' 

в принятом ответе также будут перечислены файлы, которые существуют в обоих каталогах, но имеют разное содержимое. чтобы вывести список только файлов, которые существуют в dir1, вы можете использовать:diff -r dir1 dir2 | grep 'only in' | grep dir1 | awk '{print $4}' > difference1.txt </code></pre><p>объяснение: </p><ul> <li>diff -r dir1 dir2: сравнить</li> <li>grep 'only in': получить строки, содержащие 'only in'</li> <li>grep dir1: получить строки, содержащие dir</li> </ul>

<p>это скрипт bash для печати команд для синхронизации двух каталогов</p><pre><code>dir1=/tmp/path\_to\_dir1 dir2=/tmp/path\_to\_dir2 diff -rq $dir1 $dir2 | sed -e "s|only in $dir2(.): (.)|cp -r $dir2\1/\2 $dir11|" | sed -e "s|only in $dir1\(.*\): \(.*\)|cp -r $dir11/2 $dir2\1|" </code></pre>

<p>этот ответ оптимизирует одно из предложений @ adail-junior, добавив параметр <code>-d</code>, который полезен, когда ни один из сравниваемых каталогов не является репозиторием git:</p><pre><code>git diff -d --no-index dir1/ dir2/ </code></pre><p>если вы используете <code>-d</code>, то вы не увидите сравнения с <code>/dev/null</code>: <code>text binary files a/whatever and /dev/null differ </code></p>

<p>gnu <code>grep</code> может инвертировать поиск с помощью опции <code>-v</code>. это делает <code>grep</code> отчетными строками, которые не совпадают. этим вы можете удалить файлы в <code>dir2</code> из списка файлов в <code>dir1</code>.</p><pre><code>grep -v -f -x -f <(find dir2 -type f -printf '%p\n') <(find dir1 -type f -printf '%p\n') </code></pre><p>опции <code>-f -x</code> сообщают <code>grep</code> выполнить поиск по всей строке.</p>

<p>упрощенный способ сравнения двух каталогов с помощью команды diff</p><blockquote> <blockquote> <p>diff filename.1 filename.2> filename.dat >> enter</p> </blockquote> </blockquote><p>открыть файл filename.dat после завершения запуска</p><p>и вы увидите: только в filename.1: filename.2 только в: directory\_name: name\_of\_file1 только в: directory\_name: name\_of\_file2</p>

<p> <a href="http://kdiff3.sourceforge.net">kdiff3</a> имеет приятный интерфейс diff для файлов и каталогов.</p><p>работает на windows, linux и macos.</p><p>вы можете установить его несколькими способами:</p><ul> <li>окна <ul> <li> <a href="https://sourceforge.net/projects/kdiff3/files/kdiff3/0.9.98/kdiff3-64bit-setup\_0.9.98-2.exe/download">64-битный установщик</a> </li> <li> <a href="https://sourceforge.net/projects/kdiff3/files/kdiff3/0.9.98/kdiff3-32bit-setup\_0.9.98-3.exe/download">32-битный установщик</a> </li> </ul></li> <li>macos <ul> <li> <a href="http://sourceforge.net/projects/kdiff3/files/kdiff3/0.9.98/kdiff3-0.9.98-macosx-64bit.dmg/download">бинарный</a> </li> <li>доморощенная бочка: <code>brew cask install kdiff3</code></li> </ul></li> </ul>