Разница между двумя каталогами в Linux
Я пытаюсь найти файлы, существующие в одном каталоге, но не в другом, я попытался использовать эту команду:
diff -q dir1 dir2
проблема с вышеуказанной командой в том, что она находит оба файла в dir1
а не dir2
а также файлы dir2
а не dir1
,
Я пытаюсь найти файлы dir1
а не dir2
только.
вот небольшой пример того, как выглядят мои данные
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
другой вопрос на мой взгляд, как я могу найти файлы в dir1
а не dir2
или dir3
в одной команде?
14 ответов
diff -r dir1 dir2 | grep dir1 | awk '{print }' > difference1.txt
пояснение:
diff -r dir1 dir2
показывает, какие файлы находятся только в dir1 и только в dir2, а также изменения файлов, присутствующих в обоих каталогах, если таковые имеются.diff -r dir1 dir2 | grep dir1
показывает, какие файлы находятся только в dir1awk
для печати только имени файла.
Это должно сделать работу:
diff -rq dir1 dir2
параметры объяснены (через diff (1) man page):
-
-r
- рекурсивно сравните все найденные подкаталоги. -
-q
- вывод только в том случае, если файлы отличаются.
comm -23 <(ls dir1 |sort) <(ls dir2|sort)
эта команда даст вам файлы, которые находятся в dir1 и не в директория dir2.
о <( )
знак, вы можете Google это, как подмена процесса.
хороший способ сделать это сравнение, чтобы использовать 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
эта стратегия очень полезна при сравнении двух каталогов находятся не на одной машине, и вам нужно убедиться, что файлы равны в обоих каталогах.
еще один хороший способ сделать эту работу-использовать git
git diff --no-index dir1/ dir2/
С наилучшими пожеланиями!
Meld (http://meldmerge.org/) делает большую работу по сравнению каталогов и файлов внутри.
vim DirDiff плагин-еще один очень полезный инструмент для сравнения каталогов.
vim -c "DirDiff dir1 dir2"
он не только перечисляет, какие файлы отличаются между каталогами, но также позволяет проверять/изменять с помощью vimdiff файлы, которые отличаются.
другой (возможно, более быстрый для больших каталогов) подход:
$ find dir1 | sed 's,^[^/]*/,,' | sort > dir1.txt && find dir2 | sed 's,^[^/]*/,,' | sort > dir2.txt
$ diff dir1.txt dir2.txt
на sed
команда удаляет первый компонент каталога благодаря)
Это немного поздно, но может кому-то помочь. Не уверен, что diff или rsync выплевывают только имена файлов в голом формате, как это. Спасибо plhn за предоставление этого приятного решения, которое я расширил ниже.
Если вы хотите только имена файлов, так что легко просто скопировать файлы, необходимые в чистом формате, вы можете использовать команду find.
comm -23 <(find dir1 | sed 's/dir1/\//'| sort) <(find dir2 | sed 's/dir2/\//'| sort) | sed 's/^\//dir1/'
предполагается, что dir1 и dir2 находятся в одной родительской папке. СЭД просто удаляет родительскую папку, чтобы вы могли сравнить яблоки с яблоками. Последний 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 }' > difference1.txt
объяснение:
- diff-r dir1 dir2: сравнить
- grep 'Only in': получить строки, содержащие 'Only in'
- grep dir1: получить строки, содержащие dir
неудовлетворенный всеми ответами, так как большинство из них работают очень медленно и производят излишне длинный вывод для больших каталогов, я написал свой собственный скрипт 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
или если вы хотите видеть только файлы из первого каталога:
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
P. S. Если вам нужно сравнить размеры файлов и файлов хэши для потенциальных изменений, я опубликовал обновленный скрипт здесь: https://gist.github.com/amakukha/f489cbde2afd32817f8e866cf4abe779
упрощенный способ сравнения 2 каталогов с помощью команды DIFF
diff имя файла.1 именем.2 > имя_файла.dat > > Enter
открыть именем.dat после завершения запуска
и вы увидите: Только в имени файла.1: имя.Два Только в: directory_name: name_of_file1 Только в: directory_Name: name_of_file2
kdiff3 имеет приятный интерфейс diff для файлов и каталогов.
Проверьте URL:http://kdiff3.sourceforge.net
Он работает под Windows & Linux.
GNU grep
может инвертировать поиск с помощью опции -v
. Это делает grep
отчет о строках, которые не совпадают. С помощью этого вы можете удалить файлы в dir2
из списка файлов в dir1
.
grep -v -F -x -f <(find dir2 -type f -printf '%P\n') <(find dir1 -type f -printf '%P\n')
опции -F -x
рассказать grep
для выполнения строкового поиска по всей строке.
это скрипт bash для печати команд для синхронизации двух каталогов
dir1=/tmp/path_to_dir1
dir2=/tmp/path_to_dir2
diff -rq $dir1 $dir2 | sed -e "s|Only in $dir2\(.*\): \(.*\)|cp -r $dir2/ $dir1|" | sed -e "s|Only in $dir1\(.*\): \(.*\)|cp -r $dir1/ $dir2|"