Page 1 of 1

Use of FOR in a batch file

Posted: 21 Sep 2010 03:29
by drgt
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

Re: Use of FOR in a batch file

Posted: 21 Sep 2010 05:41
by amel27

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

Use of FOR in a batch file

Posted: 21 Sep 2010 11:45
by drgt
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

Re: Use of FOR in a batch file

Posted: 21 Sep 2010 17:54
by amel27
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

Re: Use of FOR in a batch file

Posted: 22 Sep 2010 08:55
by jeb
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

Re: Use of FOR in a batch file

Posted: 22 Sep 2010 21:50
by amel27
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"
)

Re: Use of FOR in a batch file

Posted: 23 Sep 2010 03:57
by orange_batch
Good info jeb and amel27!

Re: Use of FOR in a batch file

Posted: 23 Sep 2010 11:54
by jeb
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

Use of FOR in a batch file

Posted: 11 Oct 2010 12:22
by drgt
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)

Re: Use of FOR in a batch file

Posted: 12 Oct 2010 02:05
by amel27
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

Use of FOR in a batch file

Posted: 12 Oct 2010 02:24
by drgt
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

Re: Use of FOR in a batch file

Posted: 13 Oct 2010 03:07
by amel27
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

Use of FOR in a batch file

Posted: 13 Oct 2010 11:50
by drgt
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"
)

Re: Use of FOR in a batch file

Posted: 13 Oct 2010 23:27
by amel27
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 (
....

Re: Use of FOR in a batch file

Posted: 14 Oct 2010 02:36
by ghostmachine4
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