Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Скриптовые языки администрирования Windows » CMD/BAT - Сравнение строк текстовых файлов, найти разницу.

Ответить
Настройки темы
CMD/BAT - Сравнение строк текстовых файлов, найти разницу.

Новый участник


Сообщения: 2
Благодарности: 0

Профиль | Отправить PM | Цитировать


Изменения
Автор: Alexlook
Дата: 07-11-2021
Всем привет. Нужна помощь.
Есть 2 текстовых файла, внутри каждого построчно списки файлов, 1 строка - 1 название файла. Задача найти файлы которые есть в первом файле и нет во втором и наоборот.

Вот файлы:
______________________________________________
files.txt
_________
test2.bat
test3.bat
LR.bat
LR1(‘а*ў*Ґ*ЁҐ f Ё f1 ў compare).bat
files_07.2021.txt
files_08.2021.txt
’‡ ‹ђ Ћ‘.txt
files.txt
files2.txt
files_10.2021.txt
dif.txt
test.bat
lists.txt
null
date.txt
0411.bat

________________
files2.txt
_______________
LR.bat
LR1(‘а*ў*Ґ*ЁҐ f Ё f1 ў compare).bat
files_07.2021.txt
files_08.2021.txt
’‡ ‹ђ Ћ‘.txt
files_10.2021.txt
dif.txt
test.bat
lists.txt
null
date.txt
0411.bat
0511.bat
Ђ«Ј®аЁв¬.txt
______________________________________



Пока написал вот такой код: он записывает имена файлов из файлов построчно в массивы и сравнивает, выводит если есть совпадение. Тут массивы дублируются псевдомассивами в каждой обработке файлов, это конечно можно убрать. Просто пытаюсь хоть как-то это победить. План был при совпадении строк заменять их например на 0. Затем перебрать массивы и вывести все значения что не 0 в одном списке и во втором.

Код: Выделить весь код
@echo off
Setlocal EnableDelayedExpansion EnableExtensions
chcp 866
set /a k=0
set /a l=0
set /a j=0
set /a i=0

rem получаю массив строк файла files2.txt
for /f "usebackq delims=" %%a in ("files2.txt") do (	
	set /a k+=1 	 
	set "m!k!=%%a"
	set myar[%%j]=%%a
rem	echo !myar[%%j]!
)

rem получаю массиы строк файла files.txt при это каждую строку сравниваю с каждой из предыдущего  если совпадение меняю на 0
	for /f "usebackq delims=" %%b in ("files.txt") do (
		set /a l+=1
		set "n!l!=%%b"
		set myar2[%%i]=%%b
		if !myar[%%j]! == !myar2[%%i]! do (
			echo !myar[%%j]! 
			set myar2[%%i]=0
			echo !myar2[%%i]! >> myar.txt
		)
		rem echo !myar2[%%i]!
		echo !$l%!
					
	)
	rem echo !myar2[%%i]!
	rem echo !myar[%%j]! 		
)
set /a df=12
echo %n12%
echo %m12%



Я нихрена не понимаю:

1. Почему я потом не могу циклом for /l перебрать массивы?
2. Как вывести элемент массива вне цикла не по конкретному индексу, а указывая индекс переменной. В цикле выводится а вне цикла нет.
3. Внутри цикла set myar2[%%i]=0 не меняет значения элемента. Как сделать чтоб менял?
4. Почему где-то операция в кавычках, где -то %%, где-то !!. Я конечно сам это написал но путем копипаста экспериментов и изучения кучи всяких документаций. Но по этому синтаксису внутри цикла так и не нашел ничего внятного. Если кто скажет где почитать буду признателен.
5. Если выводить переменную k или l внутри цикла она не меняет значения, только по окончании, как это работает? Где почитать?
6. Должен ли внутри цикла работать GOTO?

Если кто-то сможет с этим разобраться, возможно есть более простой способ, буду очень благодарен.

Отправлено: 16:55, 07-11-2021

 

Аватара для YuS_2

Crazy


Contributor


Сообщения: 1231
Благодарности: 515

Профиль | Отправить PM | Цитировать


Цитата Alexlook:
возможно есть более простой способ »
есть, но не в cmd, а в powershell:
Код: Выделить весь код
diff (gc files1.txt) (gc files2.txt)
результат:
Код: Выделить весь код
InputObject  SideIndicator
-----------  -------------
0511.bat     =>
Алгоритм.txt =>
test2.bat    <=
test3.bat    <=
files.txt    <=
files2.txt   <=

-------
scio me nihil scire. Ѫ

Это сообщение посчитали полезным следующие участники:

Отправлено: 18:56, 07-11-2021 | #2



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля.


Ветеран


Contributor


Сообщения: 2732
Благодарности: 1698

Профиль | Отправить PM | Цитировать


Код: Выделить весь код
@Echo Off
cls
	Set "File1=Z:\Box_In\files-1.txt"
	Set "File2=Z:\Box_In\files-2.txt"

	Echo ------- В файле "%File1%" есть а В файле "%File2%" нет
	FindStr /I /L /G:"%File2%" /V "%File1%"

	Echo ------- В файле "%File2%" есть а В файле "%File1%" нет
	FindStr /I /L /G:"%File1%" /V "%File2%"
pause
Exit /B
Тестовые данные и результат
Цитата Z:\Box_In\files-1.txt:
test1.bat
test2.bat
test21.bat
test22.bat
test31.bat
test32.bat
Цитата Z:\Box_In\files-2.txt:
test3.bat
test2.bat
test23.bat
test22.bat
test33.bat
test32.bat
Цитата Результат:
------- В файле "Z:\Box_In\files-1.txt" есть а В файле "Z:\Box_In\files-2.txt" нет
test1.bat
test21.bat
test31.bat
------- В файле "Z:\Box_In\files-2.txt" есть а В файле "Z:\Box_In\files-1.txt" нет
test3.bat
test23.bat
test33.bat
Если файлы с именами в кодировке 1251 то после cls добавить строку
Код: Выделить весь код
>nul chcp 1251
и сохранить батник в 1251 кодировке.

-------
Даже самая сложная проблема обязательно имеет простое, лёгкое для понимания, неправильное решение. Каждое решение плодит новые проблемы.


Последний раз редактировалось megaloman, 07-11-2021 в 19:55.

Это сообщение посчитали полезным следующие участники:

Отправлено: 19:44, 07-11-2021 | #3


Ветеран


Сообщения: 27449
Благодарности: 8087

Профиль | Отправить PM | Цитировать


Alexlook, глобальная цель какова? Тупо WinMerge не устроит?
Скрытый текст
Это сообщение посчитали полезным следующие участники:

Отправлено: 22:11, 07-11-2021 | #4


Аватара для Elven

Ветеран


Сообщения: 992
Благодарности: 268

Профиль | Сайт | Отправить PM | Цитировать


Цитата Alexlook:
1. Почему я потом не могу циклом for /l перебрать массивы?
2. Как вывести элемент массива вне цикла не по конкретному индексу, а указывая индекс переменной. В цикле выводится а вне цикла нет.
3. Внутри цикла set myar2[%%i]=0 не меняет значения элемента. Как сделать чтоб менял?
4. Почему где-то операция в кавычках, где -то %%, где-то !!. Я конечно сам это написал но путем копипаста экспериментов и изучения кучи всяких документаций. Но по этому синтаксису внутри цикла так и не нашел ничего внятного. Если кто скажет где почитать буду признателен.
5. Если выводить переменную k или l внутри цикла она не меняет значения, только по окончании, как это работает? Где почитать?
6. Должен ли внутри цикла работать GOTO? »
1. Потому что cmd не умеет нормально в массивы, он не хранит их сам по себе, разве что спихнуть в файл и из него прочитать. Или создать пачку переменных, и в каждую записать свое значение - получится такой как бы фальшивый массив.
2. Именно так как описано в вопросе - никак, см. п.1
3. Чтобы меняло значение, нужно использовать не %% а !!. Читать в расширенную обработку команд -> тык
4, 5. Все та же ссылка, что и в п.3
6. Должен, но использовать его не нужно. Цикл подразумевает под собой обработку некоторого количества значений до выполнения некоторого условия, в то время как GOTO совершает безусловный переход. Это не есть правильно. Кроме того - добавляет головной боли при отладке.

Что же касается создания результирующего файла мне больше нравится Compare-Object , да и для обработки массивов лучше гонять powershell. Сказать обо что-нибудь подробнее можно будет только после озвучивания окончательной цели, а то может тут большая часть телодрыжества бесполезна...
Это сообщение посчитали полезным следующие участники:

Отправлено: 08:52, 08-11-2021 | #5


Новый участник


Сообщения: 2
Благодарности: 0

Профиль | Отправить PM | Цитировать


YuS_2,
Цитата YuS_2:
Цитировать »
Спасибо, согласен в Power Shell более очевидно как это сделать. Но все же думал сделать в CMD.

Цитата megaloman:
Цитировать »
Вот это, похоже то что нужно, я findstr и fc день крутил, но видимо не до конца.
Все думал столько команд неужели нужно изобретать что-то для такой задачи.

Спасибо большое, на выходных думаю доделаю!

Цитата Iska:
Цитировать »
Глобальная цель КР по ОС:

Разработать командный файл, который формировал бы ежемесячный
отчет об изменениях в рабочем каталоге (файлы созданные, удаленные).
Необходимо хранить список файлов в файле истории.

WinMerge кажется не подойдет. Спасибо.

Цитата Elven:
Цитировать »
Спасибо за ответы и ссылки, буду разбираться.

Отправлено: 09:31, 08-11-2021 | #6


Аватара для DJ Mogarych

fascinating rhythm


Moderator


Сообщения: 6666
Благодарности: 1553

Профиль | Отправить PM | Цитировать


Цитата Alexlook:
формировал бы ежемесячный
отчет об изменениях в рабочем каталоге (файлы созданные, удаленные).
Необходимо хранить список файлов в файле истории. »
Для этого уже давно придуман файловый аудит, события которого потом легко разбираются тем же Пауэршеллом.

-------
Powershell 7.x | Powershell 5.1 | ffmpeg (docs)

Это сообщение посчитали полезным следующие участники:

Отправлено: 10:18, 08-11-2021 | #7


Ветеран


Contributor


Сообщения: 2732
Благодарности: 1698

Профиль | Отправить PM | Цитировать


Alexlook,
Цитата:
Почему ...
Не умеете Если нельзя но очень хочется, то можно (осторожно)
Код: Выделить весь код
@Echo Off
cls
	Call :TxtToMass "Z:\Box_In\Файл первый.txt" "@@A" "NA" 10000

	Set "@@A"
	Echo NA=%NA%
	Echo @@A10005=%@@A10005%
	Echo.

	Call :TxtToMass "Z:\Box_In\Файл второй.txt" "@@B" "NB" 10000

	Set "@@B"
	Echo NB=%NB%
	Echo @@B10003=%@@A10003%
	Echo.

	For /L %%i In (10001,1,%NA%) Do Call Echo %%i %%@@A%%i%%
	Echo.

	For /F "usebackq tokens=1* delims==" %%i In (`Set "@@A"`) Do Echo %%i %%j
	Echo.

pause
Exit /B

:TxtToMass
	Set /A %~3=%~4
	For /F "usebackq delims=" %%i In (`2^>nul More %1`) Do (
		Call Set /A %~3+=1
		Call Set "%~2%%%~3%%=%%i"
	)
Exit /B
Пояснения
Цитата Elven:
создать пачку переменных, и в каждую записать свое значение - получится такой как бы фальшивый массив. »
В моём примере так и реализовано. Только для того, чтобы при сортировке элементов массива по имени не нарушался порядок строк из текстового файла я нумерую элементы псевдомассива не 1, 2, 3 а, например, 10001, 10002, 10003. Если делать не так, то при текстовой сортировке имён получим что A100 будет отображаться раньше A2.
Я стараюсь избегать применения Setlocal EnableDelayedExpansion так как применение ! в текстовых литералах при этом приведёт к ошибке. Для Вашего случая, в имени файлов при таком SetLocal не должно быть "!".
Но вообще-то работать с текстами в CMD - надо очень осторожно, есть много служебных символов в CMD, которые, если встретятся в литерале, сломают любую вашу логику.
В примере я применил процедуру (кто-то меня поправит - псевдопроцедуру)
Для облегчения понимания её работы вот кусок для одного массива (псевдомассива, чтобы никого не раздражать) без процедуры.
Код: Выделить весь код
@Echo Off
cls
	Set /A NA=10000
	For /F "usebackq delims=" %%i In (`2^>nul More "Z:\Box_In\Файл первый.txt"`) Do (
		Call Set /A NA+=1
		Call Set "@@A%%NA%%=%%i"
	)

	Set "@@A"
	Echo NA=%NA%
	Echo @@A10005=%@@A10005%
	Echo.

	For /L %%i In (10001,1,%NA%) Do Call Echo %%i %%@@A%%i%%
	Echo.

	For /F "usebackq tokens=1* delims==" %%i In (`Set "@@A"`) Do Echo %%i %%j
	Echo.
pause
Exit /B
Процедура удобнее, особенно если одно и то же надо проделать в нескольких местах.
Насчёт GoTo в цикле
Если GoTo ссылается на метку внутри цикла, у меня не получается. Я использую GoTo внутри цикла на метку вне цикла, чтобы выйти из цикла.
Лучше использовать If
Код: Выделить весь код
@Echo Off
cls
	For /L %%i In (1,1,10) Do (
		If %%i LEQ 5 (
			Echo %%i меньше или равно 5
		) Else (
			Echo %%i больше 5
		)
	)
pause
Exit /B

-------
Даже самая сложная проблема обязательно имеет простое, лёгкое для понимания, неправильное решение. Каждое решение плодит новые проблемы.


Последний раз редактировалось megaloman, 08-11-2021 в 11:46.

Это сообщение посчитали полезным следующие участники:

Отправлено: 10:57, 08-11-2021 | #8


Deadooshka


Сообщения: 2558
Благодарности: 697

Профиль | Отправить PM | Цитировать


Нету там никаких массивов. Квадратные скобки - часть имени переменной.

Отправлено: 11:01, 08-11-2021 | #9


Ветеран


Сообщения: 27449
Благодарности: 8087

Профиль | Отправить PM | Цитировать


Цитата Alexlook:
Глобальная цель КР по ОС:
Разработать командный файл, который формировал бы ежемесячный
отчет об изменениях в рабочем каталоге (файлы созданные, удаленные).
Необходимо хранить список файлов в файле истории. »
Используйте код коллеги megaloman из сообщения №3.

Отправлено: 00:47, 09-11-2021 | #10



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Скриптовые языки администрирования Windows » CMD/BAT - Сравнение строк текстовых файлов, найти разницу.

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
CMD/BAT - Как сравнить разницу в двух текстовых документах и вывести разницу в новый текстовый mrusklon Скриптовые языки администрирования Windows 6 31-10-2019 17:05
Любой язык - [решено] Сравнение 2-х текстовых файлов и удаление дубликатов строк в 1-м файле. Uragan66 Скриптовые языки администрирования Windows 2 26-05-2019 16:14
CMD/BAT - Сравнение чисел в .txt и двух текстовых файлов papacoca Скриптовые языки администрирования Windows 14 01-03-2019 08:00
Сравнение текстовых файлов Speedy Программное обеспечение Windows 9 30-03-2015 02:42
Офис и Текст - Автоматическое сравнение текстовых файлов Kzer-Za Программное обеспечение Windows 4 04-10-2011 11:50




 
Переход