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

Ответить
Аватара пользователя
Alexlook

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

Сообщение Alexlook »

Всем привет. Нужна помощь.

Есть 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?



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

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

Сообщение YuS_2 »

Цитата Alexlook:



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




есть, но не в cmd, а в powershell:



Код:

Код: Выделить всё

diff (gc files1.txt) (gc files2.txt)

результат:



Код:

Код: Выделить всё

InputObject  SideIndicator
-----------  -------------
0511.bat     =>
Алгоритм.txt =>
test2.bat    
Аватара пользователя
megaloman

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

Сообщение megaloman »

Код:

Код: Выделить всё

@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




Тестовые данные и результат

[spoiler]Цитата Z:\Box_In\files-1.txt:[/spoiler]



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 кодировке.
Аватара пользователя
Iska

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

Сообщение Iska »

Alexlook, глобальная цель какова? Тупо WinMerge не устроит?



Скрытый текст

[spoiler]Изображение[/spoiler]
Аватара пользователя
Elven

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

Сообщение Elven »

Цитата Alexlook:



1. Почему я потом не могу циклом for /l перебрать массивы?

2. Как вывести элемент массива вне цикла не по конкретному индексу, а указывая индекс переменной. В цикле выводится а вне цикла нет.

3. Внутри цикла set myar2[%%i]=0 не меняет значения элемента. Как сделать чтоб менял?

4. Почему где-то операция в кавычках, где -то %%, где-то !!. Я конечно сам это написал но путем копипаста экспериментов и изучения кучи всяких документаций. Но по этому синтаксису внутри цикла так и не нашел ничего внятного. Если кто скажет где почитать буду признателен.

5. Если выводить переменную k или l внутри цикла она не меняет значения, только по окончании, как это работает? Где почитать?

6. Должен ли внутри цикла работать GOTO?
CMD/BAT - Сравнение строк текстовых файлов, найти разницу.




1. Потому что cmd не умеет нормально в массивы, он не хранит их сам по себе, разве что спихнуть в файл и из него прочитать. Или создать пачку переменных, и в каждую записать свое значение - получится такой как бы фальшивый массив.

2. Именно так как описано в вопросе - никак, см. п.1

3. Чтобы меняло значение, нужно использовать не %% а !!. Читать в расширенную обработку команд ->
тык


4, 5. Все та же ссылка, что и в п.3

6. Должен, но использовать его не нужно. Цикл подразумевает под собой обработку некоторого количества значений до выполнения некоторого условия, в то время как GOTO совершает безусловный переход. Это не есть правильно. Кроме того - добавляет головной боли при отладке.



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

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

Сообщение Alexlook »

YuS_2,
Цитата YuS_2:



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




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




Цитата megaloman:



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




Вот это, похоже то что нужно, я findstr и fc день крутил, но видимо не до конца.

Все думал столько команд неужели нужно изобретать что-то для такой задачи.



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




Цитата Iska:



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




Глобальная цель КР по ОС:



Разработать командный файл, который формировал бы ежемесячный

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

Необходимо хранить список файлов в файле истории.



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




Цитата Elven:



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




Спасибо за ответы и ссылки, буду разбираться.
Аватара пользователя
DJ Mogarych

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

Сообщение DJ Mogarych »

Цитата Alexlook:



формировал бы ежемесячный

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

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




Для этого уже давно придуман файловый аудит, события которого потом легко разбираются тем же Пауэршеллом.
Аватара пользователя
megaloman

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

Сообщение megaloman »

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




Пояснения

[spoiler]Цитата Elven:[/spoiler]



создать пачку переменных, и в каждую записать свое значение - получится такой как бы фальшивый массив.
CMD/BAT - Сравнение строк текстовых файлов, найти разницу.




В моём примере так и реализовано. Только для того, чтобы при сортировке элементов массива по имени не нарушался порядок строк из текстового файла я нумерую элементы псевдомассива не 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 в цикле

[spoiler]Если GoTo ссылается на метку внутри цикла, у меня не получается. Я использую GoTo внутри цикла на метку вне цикла, чтобы выйти из цикла.

Лучше использовать If

Код:
[/spoiler]

Код: Выделить всё

@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
Аватара пользователя
Sham

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

Сообщение Sham »

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

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

Сообщение Sham »

Цитата Alexlook:



Глобальная цель КР по ОС:

Разработать командный файл, который формировал бы ежемесячный

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

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




Используйте код коллеги megaloman из
CMD/BAT - Сравнение строк текстовых файлов, найти разницу.
.
Ответить

Вернуться в «Скриптовые языки администрирования Windows»