2

I'm trying to write a script that will find all directory junctions on a disk and then recreate them in another location. First of all, I have to find all the junctions and edit the output to be more readable.

This is the test.txt:

 Volume in drive C has no label.
 Volume Serial Number is A0D2-DFB0

 Directory of C:\

14.07.2009.  06:08    <JUNCTION>     Documents and Settings [C:\Users]
13.01.2015.  10:26    <JUNCTION>     Users [E:\Users]
               0 File(s)              0 bytes

 Directory of C:\ProgramData

14.07.2009.  06:08    <JUNCTION>     Application Data [C:\ProgramData]
14.07.2009.  06:08    <JUNCTION>     Desktop [C:\Users\Public\Desktop]
14.07.2009.  06:08    <JUNCTION>     Documents [C:\Users\Public\Documents]
14.07.2009.  06:08    <JUNCTION>     Favorites [C:\Users\Public\Favorites]
14.07.2009.  06:08    <JUNCTION>     Start Menu [C:\ProgramData\Microsoft\Windows\Start Menu]
14.07.2009.  06:08    <JUNCTION>     Templates [C:\ProgramData\Microsoft\Windows\Templates]
               0 File(s)              0 bytes

 Directory of C:\ProgramData\Oracle\Java\javapath

24.12.2014.  18:22    <SYMLINK>      java.exe [D:\Programs\Java 8u25\bin\java.exe]
24.12.2014.  18:22    <SYMLINK>      javaw.exe [D:\Programs\Java 8u25\bin\javaw.exe]
24.12.2014.  18:22    <SYMLINK>      javaws.exe [D:\Programs\Java 8u25\bin\javaws.exe]
               3 File(s)              0 bytes

     Total Files Listed:
               3 File(s)              0 bytes
               8 Dir(s)  16.309.276.672 bytes free

- This is the (unfinished) script that I'm running:

echo on

cd \

set start=
set end=
set paths=

type NUL > output.txt

for /f "tokens=* skip=3" %%l in (C:\test.txt) do (
for /f "tokens=1" %%d in ("%%l") do (
 if %%d==Directory (
    for /f "tokens=3" %%p in ("%%l") do (
      set start="%%p"
    )
 ) else (
   for /f "tokens=3" %%j in ("%%l") do (
      if %%j==^<JUNCTION^> (
          for /f "tokens=4*" %%h in ("%%l") do (
            set end="%%h"
            echo %start% %end% >> output.txt

          )
       )
    )
 )
)
)

Problem is that output.txt ends up with several lines of "Echo is ON" instead of having paths in there. If I substitute "%start% %end%" with any string (eg. "sausage") I get output.txt filled with sausages. If I run echo set %end% after the script runs, output is "Templates" which is expected. I'm guessing that set command doesn't set anything until one of the loops is done.

Am I right? Is there a way around that? I really need to get this working in CMD because it has to be run from Windows Repair disk.

P.S. I know my code won't work for my purpose even with this program fixed, but I'm just getting there, first things first.

8
  • set does not work in ( ) because a batch file is not actually processed in that order. Basically the entire script without code between ( ) is exeucted, and then the part between ( ) is executed. You can overcome this by writing the second code in a second batch file and execute that in your FOR statement. The first one, you can place the set line entirely on the FOR line and remove the ( ) all together.
    – LPChip
    Jan 14, 2015 at 23:03
  • also, to ommit the other ( ), use goto variable and :variable.
    – LPChip
    Jan 14, 2015 at 23:04
  • @LPChip - your solution can work, but not for the reason you state.
    – dbenham
    Jan 15, 2015 at 4:40
  • schinagl.priv.at/nt/ln/ln.html
    – STTR
    Jan 15, 2015 at 6:01
  • @dbenham by all means enlighten us why you say so. I found out that when I have scripts like this, the SET command always has the last variable set in the loop, so I assumed it isn't processed in actual order.
    – LPChip
    Jan 15, 2015 at 7:41

2 Answers 2

1

If you use your original script and add setlocal enabledelayedexpansion you can replace %start% and %end% by !start! and !end! and your script will work as you intended.

Your script doesn't allow for blanks in the file names, so I propose the following modified script:-

echo off

setlocal enabledelayedexpansion

cd \

set start=
set end=
set paths=

type NUL > output.txt

for /f "tokens=* skip=3" %%l in (C:\test.txt) do ^
for /f "tokens=1-2*" %%d in ("%%l") do ^
if %%d==Directory (
    set start="%%f"
) else (
    for /f "tokens=3*" %%j in ("%%l") do ^
if %%j==^<JUNCTION^> (
            for /f "tokens=1 delims=[" %%n in ("%%k") do set end=%%n
            set end="!end:~0,-1!"
            echo !start! !end! >> output.txt

        )
)

I have done two additional things here:-

  1. I have removed brackets from the commands that do not need it (unfortunately, the new line after the continuation character ^ cannot be indented, which spoils the formatting of the second if).
  2. I have removed unnecessary for loops while at the same time allowing for embedded blanks in the directory and file names.

I have left them in, but the initial cd \ and set initialisations are unnecessary, though you may wish to clear start and end before exiting.

1
  • Thank you very much, this is exactly what I have been looking for. Jan 30, 2015 at 18:00
1

Replace echo %start% %end% >> output.txt with call :forecho and attach next code snippet beneath the last script line:

goto :eof

:forecho
    echo %start% %end% >> output.txt
goto :eof

Problem lays in fact that %variables% are expanded, command by command, at parse time rather than at execution time. And all code snippet enclosed in (parenthheses) is considered to be an only command.

To be on the safe side, start your script with

@ECHO OFF >NUL
@SETLOCAL enableextensions disabledelayedexpansion

Whole script then could be as follows:

@ECHO OFF >NUL
@SETLOCAL enableextensions disabledelayedexpansion
cd \
set start=
set end=
set paths=
type NUL > output.txt

for /f "tokens=* skip=3" %%l in (C:\test.txt) do (
for /f "tokens=1" %%d in ("%%l") do (
 if %%d==Directory (
    for /f "tokens=3" %%p in ("%%l") do (
      set start="%%p"
    )
 ) else (
   for /f "tokens=3" %%j in ("%%l") do (
      if %%j==^<JUNCTION^> (
          for /f "tokens=4*" %%h in ("%%l") do (
            set end="%%h"
            call :forecho
          )
       )
    )
 )
)
)
@ENDLOCAL
goto :eof

:forecho
    echo %start% %end% >> output.txt
goto :eof

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .