Use of FOR in a batch file

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
drgt
Posts: 160
Joined: 21 Sep 2010 02:22
Location: Greece

Use of FOR in a batch file

#1 Post by drgt » 21 Sep 2010 03:29

Hi

I have 2 directories with the same files and I want to compare them using fc.exe. I do not quite understand how the "for...in...do" works.

I would also like to take advantage of fc's errorlevels if a file is not found for example.

I know how to redirect the dir command to create a list of the files I want to compare.

Thanks

amel27
Expert
Posts: 177
Joined: 04 Jun 2010 20:05
Location: Russia

Re: Use of FOR in a batch file

#2 Post by amel27 » 21 Sep 2010 05:41

Code: Select all

@echo off

set d1=c:\test1
set d2=d:\test2

echo -----
echo :1 2:
echo -----

for /f "delims=" %%i in ('dir /b/a-d "%d1%\*" "%d2%\*"^|sort') do (
  call set "$i=%%$i:%%i=%%"
  if defined $i (
    if not exist "%d1%\%%i" (echo :. +: %%i) else (
    if not exist "%d2%\%%i" (echo :+ .: %%i) else (
    fc "%d1%\%%i" "%d2%\%%i" >nul&& echo := =: %%i|| echo :^< ^>: %%i)))
  set "$i=%%i"
)

P.S. files w/o subfolders

drgt
Posts: 160
Joined: 21 Sep 2010 02:22
Location: Greece

Use of FOR in a batch file

#3 Post by drgt » 21 Sep 2010 11:45

Cool!!!!
Even better than the one I had in mind! Very creative!

I have to learn this stuff. What's a good place to go?

PS. What if I want nothing displayed when files are equal?

Thanks again

amel27
Expert
Posts: 177
Joined: 04 Jun 2010 20:05
Location: Russia

Re: Use of FOR in a batch file

#4 Post by amel27 » 21 Sep 2010 17:54

drgt wrote:I have to learn this stuff. What's a good place to go?
may be here and here

drgt wrote:What if I want nothing displayed when files are equal?
delete from fc command line positive (&&) alternative
another method via enabledelayedexpansion, and w/o equal files:

Code: Select all

@echo off
setlocal enabledelayedexpansion

set d1=c:\in
set d2=d:\out

echo -----
echo :1 2:
echo -----

for /f "delims=" %%i in ('dir /b/a-d "%d1%\*" "%d2%\*"^|sort') do (
  if /i not "!$i!"=="%%i" (
    if not exist "%d1%\%%i" (echo :. +: %%i) else (
    if not exist "%d2%\%%i" (echo :+ .: %%i) else (
    fc "%d1%\%%i" "%d2%\%%i" >nul|| echo :^< ^>: %%i)))
  set "$i=%%i"
)


P.S. file names must not contains "!" symbol

jeb
Expert
Posts: 1055
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: Use of FOR in a batch file

#5 Post by jeb » 22 Sep 2010 08:55

amel27 wrote:P.S. file names must not contains "!" symbol


File names can contains also "!" symbols, if you change the code a little bit.

Code: Select all

@echo off
setlocal enabledelayedexpansion

set d1=c:\in
set d2=d:\out

echo -----
echo :1 2:
echo -----

for /f "delims=" %%i in ('dir /b/a-d "%d1%\*" "%d2%\*"^|sort') do (
  setlocal Disabledelayedexpansion
  set "fName=%%i"
  setlocal enabledelayedexpansion
  if /i not "!$i!"=="!fName!" (
    if not exist "%d1%\!fName!" (echo :. +: !fName!) else (
    if not exist "%d2%\!fName!" (echo :+ .: !fName!) else (
    fc "%d1%\!fName!" "%d2%\!fName!" >nul || echo :^< ^>: !fName!)))
  set "$i=!fName!"
)


jeb

amel27
Expert
Posts: 177
Joined: 04 Jun 2010 20:05
Location: Russia

Re: Use of FOR in a batch file

#6 Post by amel27 » 22 Sep 2010 21:50

no! such code lead to an error:
Maximum setlocal recursion level reached.

SetLocal/EndLocal must each be paired with a matching end, especially in loop:

Code: Select all

@echo off
SetLocal DisableDelayedExpansion

set d1=c:\test1
set d2=d:\test2

echo -----
echo :1 2:
echo -----

for /f "delims=" %%i in ('dir /b/a-d "%d1%\*" "%d2%\*"^|sort') do (
  set "$f=%%i"& SetLocal EnableDelayedExpansion
  if /i not "!$i!"=="!$f!" (
    if not exist "%d1%\!$f!" (echo :. +: !$f!) else (
    if not exist "%d2%\!$f!" (echo :+ .: !$f!) else (
    fc "%d1%\!$f!" "%d2%\!$f!" >nul|| echo :^< ^>: !$f!)))
  EndLocal& set "$i=%%i"
)

orange_batch
Expert
Posts: 442
Joined: 01 Aug 2010 17:13
Location: Canadian Pacific
Contact:

Re: Use of FOR in a batch file

#7 Post by orange_batch » 23 Sep 2010 03:57

Good info jeb and amel27!

jeb
Expert
Posts: 1055
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: Use of FOR in a batch file

#8 Post by jeb » 23 Sep 2010 11:54

amel27 wrote:no! such code lead to an error:


Yes, you got me, i didn't test it. :)
It only works with a few number of lines.

And of course it's really bad style to use setlocal without endlocal.

jeb

drgt
Posts: 160
Joined: 21 Sep 2010 02:22
Location: Greece

Use of FOR in a batch file

#9 Post by drgt » 11 Oct 2010 12:22

Hi Amel27,

Why if run for 2nd time it behaves differently? see below:

-----------------------------------
C:\>fico
-----
:1 2:
-----
:= =: New Text Document.txt

C:\>fico
-----
:1 2:
-----

C:\>
-------------------------------------

fico is the name of the file (fico.bat)

amel27
Expert
Posts: 177
Joined: 04 Jun 2010 20:05
Location: Russia

Re: Use of FOR in a batch file

#10 Post by amel27 » 12 Oct 2010 02:05

drgt wrote:Why if run for 2nd time it behaves differently?

sorry, but I can't verify you result, in my test results is identical

drgt
Posts: 160
Joined: 21 Sep 2010 02:22
Location: Greece

Use of FOR in a batch file

#11 Post by drgt » 12 Oct 2010 02:24

amel27 wrote:sorry, but I can't verify you result, in my test results is identical


How is it possible? Are we running the same code? My second run is as posted above.

Here is the code:
----------------------
@echo off

set d1=C:\Test\Comp1
set d2=C:\Test\Comp2

echo -----
echo :1 2:
echo -----

for /f "delims=" %%i in ('dir /b/a-d "%d1%\*" "%d2%\*"^|sort') do (
call set "$i=%%$i:%%i=%%"
if defined $i (
if not exist "%d1%\%%i" (echo :. +: %%i) else (
if not exist "%d2%\%%i" (echo :+ .: %%i) else (
fc "%d1%\%%i" "%d2%\%%i" >nul&& echo := =: %%i|| echo :^< ^>: %%i)))
set "$i=%%i"
)
------------------------

Please check again

amel27
Expert
Posts: 177
Joined: 04 Jun 2010 20:05
Location: Russia

Re: Use of FOR in a batch file

#12 Post by amel27 » 13 Oct 2010 03:07

drgt wrote:Please check again

sorry, not verify again

- try on another comp;
- try this last edition:

Code: Select all

@echo off
SetLocal DisableDelayedExpansion

set d1=c:\test1
set d2=d:\test2

echo -----
echo :1 2:
echo -----

for /f "delims=" %%i in ('dir /b/a-d "%d1%\*" "%d2%\*"^|sort') do (
  set "$f=%%i"& SetLocal EnableDelayedExpansion
  if /i not "!$i!"=="!$f!" (
    if not exist "%d1%\!$f!" (echo :. +: !$f!) else (
    if not exist "%d2%\!$f!" (echo :+ .: !$f!) else (
    fc "%d1%\!$f!" "%d2%\!$f!" >nul&& echo := =: !$f!|| echo :^< ^>: !$f!)))
  EndLocal& set "$i=%%i"
)

- try debug both attempts with full logging (with 1'st @echo on)

Code: Select all

fico.cmd >fico_1.log 2>&1
fico.cmd >fico_2.log 2>&1

with detailed compare this tow logs

drgt
Posts: 160
Joined: 21 Sep 2010 02:22
Location: Greece

Use of FOR in a batch file

#13 Post by drgt » 13 Oct 2010 11:50

Here are the requested logs.

You see the 2nd run is different. I am running xp media center sp2. Do I have a different command interpreter?

THE CODE YOU ARE SUGGESTING IN PREVIOUS POST ALSO YIELDED NOTHING PERHAPS BECAUSE I RUN IT AFTER THE CODE HEREIN.

I RUN "SET" AFTER THESE BATCHES:
C:\>SET
$i=New Text Document.txt
d1=C:\Test\Comp1
d2=C:\Test\Comp2

SHOULD NOT THESE BE CLEARED AT THE END OF THE BATCH FILE?
COULD THIS BE THE CAUSE OF THE PROBLEM?

fico_log1:
-----------
C:\>rem @echo off

C:\>set d1=C:\Test\Comp1

C:\>set d2=C:\Test\Comp2

C:\>echo -----
-----

C:\>echo :1 2:
:1 2:

C:\>echo -----
-----

C:\>for /F "delims=" %i in ('dir /b/a-d "C:\Test\Comp1\*" "C:\Test\Comp2\*"|sort') do (
call set "$i=%$i:%i=%"
if defined $i (if not exist "C:\Test\Comp1\%i" (echo :. +: %i ) else (if not exist "C:\Test\Comp2\%i" (echo :+ .: %i ) else (fc "C:\Test\Comp1\%i" "C:\Test\Comp2\%i" 1>nul && echo := =: %i || echo :< >: %i ) ) )
set "$i=%i"
)

C:\>(
call set "$i=%$i:New Text Document.txt=%"
if defined $i (if not exist "C:\Test\Comp1\New Text Document.txt" (echo :. +: New Text Document.txt ) else (if not exist "C:\Test\Comp2\New Text Document.txt" (echo :+ .: New Text Document.txt ) else (fc "C:\Test\Comp1\New Text Document.txt" "C:\Test\Comp2\New Text Document.txt" 1>nul && echo := =: New Text Document.txt || echo :< >: New Text Document.txt ) ) )
set "$i=New Text Document.txt"
)
:= =: New Text Document.txt

C:\>(
call set "$i=%$i:New Text Document.txt=%"
if defined $i (if not exist "C:\Test\Comp1\New Text Document.txt" (echo :. +: New Text Document.txt ) else (if not exist "C:\Test\Comp2\New Text Document.txt" (echo :+ .: New Text Document.txt ) else (fc "C:\Test\Comp1\New Text Document.txt" "C:\Test\Comp2\New Text Document.txt" 1>nul && echo := =: New Text Document.txt || echo :< >: New Text Document.txt ) ) )
set "$i=New Text Document.txt"
)

========================================

fico_log2:
------------
C:\>rem @echo off

C:\>set d1=C:\Test\Comp1

C:\>set d2=C:\Test\Comp2

C:\>echo -----
-----

C:\>echo :1 2:
:1 2:

C:\>echo -----
-----

C:\>for /F "delims=" %i in ('dir /b/a-d "C:\Test\Comp1\*" "C:\Test\Comp2\*"|sort') do (
call set "$i=%$i:%i=%"
if defined $i (if not exist "C:\Test\Comp1\%i" (echo :. +: %i ) else (if not exist "C:\Test\Comp2\%i" (echo :+ .: %i ) else (fc "C:\Test\Comp1\%i" "C:\Test\Comp2\%i" 1>nul && echo := =: %i || echo :< >: %i ) ) )
set "$i=%i"
)

C:\>(
call set "$i=%$i:New Text Document.txt=%"
if defined $i (if not exist "C:\Test\Comp1\New Text Document.txt" (echo :. +: New Text Document.txt ) else (if not exist "C:\Test\Comp2\New Text Document.txt" (echo :+ .: New Text Document.txt ) else (fc "C:\Test\Comp1\New Text Document.txt" "C:\Test\Comp2\New Text Document.txt" 1>nul && echo := =: New Text Document.txt || echo :< >: New Text Document.txt ) ) )
set "$i=New Text Document.txt"
)
MISSING!!!!!!!!!!
C:\>(
call set "$i=%$i:New Text Document.txt=%"
if defined $i (if not exist "C:\Test\Comp1\New Text Document.txt" (echo :. +: New Text Document.txt ) else (if not exist "C:\Test\Comp2\New Text Document.txt" (echo :+ .: New Text Document.txt ) else (fc "C:\Test\Comp1\New Text Document.txt" "C:\Test\Comp2\New Text Document.txt" 1>nul && echo := =: New Text Document.txt || echo :< >: New Text Document.txt ) ) )
set "$i=New Text Document.txt"
)

amel27
Expert
Posts: 177
Joined: 04 Jun 2010 20:05
Location: Russia

Re: Use of FOR in a batch file

#14 Post by amel27 » 13 Oct 2010 23:27

the code to reproduce error is:

Code: Select all

call fico.cmd
call fico.cmd

this occur because $i var interfered between calls, you must clear it before

Code: Select all

set $i=& for /f "delims=" %%i in ('dir /b/a-d "%d1%\*" "%d2%\*"^|sort') do (
....

ghostmachine4
Posts: 319
Joined: 12 May 2006 01:13

Re: Use of FOR in a batch file

#15 Post by ghostmachine4 » 14 Oct 2010 02:36

drgt wrote:Hi

I have 2 directories with the same files and I want to compare them using fc.exe. I do not quite understand how the "for...in...do" works.

I would also like to take advantage of fc's errorlevels if a file is not found for example.

I know how to redirect the dir command to create a list of the files I want to compare.

Thanks

You have posted since Sep and until now, you have not solved your problem.
Long ago since the time when there is Unix, the diff tool is used just for this purpose, comparing 2 directories( and files as wells). Now, on windows, you can use diff as well..download diff for windows here. then its simply

Code: Select all

diff c:\dir1 c:\dir2


No need to reinvent the wheel. you will be more productive using the correct tools for the job

Post Reply