3

I am referring to below threat Batch files: How to read a file?. For retrieving the line by line from a text file. I am using the below script:

@echo off
SETLOCAL DisableDelayedExpansion
FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ paths.txt"`) do (
    set "var=%%a"
    SETLOCAL EnableDelayedExpansion
    set "var=!var:*:=!"
    echo !var!
    ENDLOCAL
)

Code is working fine! The values in !var! can not assign to any variable. :( I struct there, Please anyone help to read line by line and I wish to assign to some variable and want to manipulate that variable. Please help to solve this situation.

Update:

@ECHO off

CLS

SET PROJ_DIR=D:\workspace\proj
SET PROMO_DIR=D:\TEST
SET SOURCE_CODE=\Source Code

SETLOCAL DisableDelayedExpansion
for /f %%a in (paths.txt) do (
    SET "var=%%a"
    SETLOCAL EnableDelayedExpansion
    set "var=!var:*:=!"
    set FILE_PATH=!var://www.domain.com/path/dir=!
    SET FILE_PATH=!FILE_PATH:/=\!
    SET PROMO_FILE_PATH=!PROMO_DIR!!SOURCE_CODE!!FILE_PATH! 
    FOR %%i IN ("!PROMO_FILE_PATH!") DO SET FOLDER_PATH=%%~dpi
    FOR %%i IN ("!PROMO_FILE_PATH!") DO SET FILE_NAME=%%~nxi
    IF EXIST "!FOLDER_PATH!" GOTO F3
        MKDIR "!FOLDER_PATH!"
    :F3
    IF NOT EXIST "!PROJ_DIR!!FILE_PATH!" GOTO F4
        COPY "!PROJ_DIR!!FILE_PATH!" "!FOLDER_PATH!"
    :F4
        ECHO Cannot find the file under "!PROJ_DIR!!FILE_PATH!"

    ENDLOCAL
)

SET CLOSE_CONFIRM=
SET /P CLOSE_CONFIRM=Press any key to close the window...%=%

paths.txt

//www.domain.com/path/dir/dir1/dir2/file1.txt 
//www.domain.com/path/dir/dir1/dir2/file2.txt 
//www.domain.com/path/dir/dir1/dir2/file3.txt 
//www.domain.com/path/dir/dir1/dir2/file4.txt 
//www.domain.com/path/dir/dir1/dir3/file1.txt

Command Output

        1 file(s) copied.
Cannot find the file under "D:\workspace\proj\dir1\dir2\file1.txt"
        1 file(s) copied.
Cannot find the file under "D:\workspace\proj\dir1\dir2\file2.txt"
Press any key to close the window...

thanks..

Community
  • 1
  • 1
Mohamed Saligh
  • 12,029
  • 19
  • 65
  • 84
  • 1
    A simple `set "myVar2=!var!"` should work, or do you try to access the variable after the `endlocal`? – jeb Jun 08 '11 at 12:36
  • It does't work for me :( i tried `"myvar2=!var!"` and then `echo %myvar2%`. But, it is not printing anything. It simply prints `ECHO is on`. What can I do? please help on this. thanks – Mohamed Saligh Jun 08 '11 at 14:46
  • The assignment works, but your echo fails, as percent expansion is done only once BEFORE the Loop is executed. Change it to `echo !myvar2!` – jeb Jun 08 '11 at 17:29
  • You should show the input file and/or add some debug outputs into your code like `echo !var! !FILE_PATH!` – jeb Jun 09 '11 at 10:02
  • well, I got the issue. I hope you can understand my piece of code. The problem is that when a particular folder has more than 2 files. It can copy only two files and then terminating the process. that is the problem with my code. why is that happening? – Mohamed Saligh Jun 09 '11 at 10:06
  • You can't use goto labels inside a loop, it breaks the loop – jeb Jun 09 '11 at 10:15

4 Answers4

2

The key is the delayed expansion, expand your variables inside of parenthesis always with ! not with %.

A sample that changes X with Y

@echo off
SETLOCAL DisableDelayedExpansion
FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ paths.txt"`) do (
    set "var=%%a"
    SETLOCAL EnableDelayedExpansion
    set "var=!var:*:=!"
    set "myVar=!var!"
    set "myVar=!myVar:X=Y!"
    echo X replaced with Y =!myVar! 
    ENDLOCAL
)

In your updated version the goto :label stops the for-loop immediatly

Better rewrite it to IF-Blocks

IF NOT EXIST "!FOLDER_PATH!" (
  MKDIR "!FOLDER_PATH!"
)
IF EXIST "!PROJ_DIR!!FILE_PATH!" (
    COPY "!PROJ_DIR!!FILE_PATH!" "!FOLDER_PATH!"
) ELSE
(
    ECHO Cannot find the file under "!PROJ_DIR!!FILE_PATH!"
)
jeb
  • 78,592
  • 17
  • 171
  • 225
2

The other answers here cover the tricky bits of delayed expansion in this code. I want to add that you can often avoid most delayed expansion problems by rolling the parentheses out into a subroutine.

FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ paths.txt"`) do call :HandlePath %%a
goto :eof

================
:HandlePath
set "var=%*"
set "var=%var:*:=%"
echo %var%
goto :eof

I find this code easier to maintain because each line is parsed an executed exactly when you would expect.

Ryan Bemrose
  • 9,018
  • 1
  • 41
  • 54
  • +1, Good hint for simple problems, but this will fail dependent on the line contents, you can not handle lines like `A difficult text "&"&` with percent expansion nor with calling parameters – jeb Jun 29 '11 at 21:38
1

If you want to read each line and manipulate it:

SETLOCAL EnableDelayedExpansion
FOR /F "tokens=*" %%a IN (paths.txt) DO (
set var=%%a
ECHO %var%
PAUSE
)
ENDLOCAL

If you are trying to search a string from a file and manipulate it:

SETLOCAL EnableDelayedExpansion
FOR /F "tokens=* usebackq" %%a IN (`FIND /I 'string to search for' "C:\folder\paths.txt"`) DO (
set var=%%a
ECHO %var%
PAUSE
)
ENDLOCAL

If you are trying to search a string and manipulate each word in the string:

SETLOCAL EnableDelayedExpansion
FOR /F "usebackq tokens=1-999 delims= " %%a IN (`FIND /I 'string to search for' "C:\folder\paths.txt"`) DO (
REM %%a = first word  %%b = second word etc. through the alphabet
set var1=%%a%%b%%c
set var2=%%d
ser var3=%%e
ECHO %var1% %var2% %var3%
PAUSE
)
ENDLOCAL
Anthony Miller
  • 15,101
  • 28
  • 69
  • 98
  • It just prints `ECHO is off`. I cant assign like `var2=!var!`. – Mohamed Saligh Jun 08 '11 at 15:48
  • and a quick question... are you trying to search for specific strings in the text file or you want all lines to be read? And I've never seen !var:*:=! used before... what does :*:= supposed to do to the variable? – Anthony Miller Jun 08 '11 at 15:54
  • thanks for your prompt response, well I am trying to read line by line from a file and I just want to manipulate that line... this is what I want to achieve... – Mohamed Saligh Jun 08 '11 at 16:09
  • Your echo's can't work as the %var1% %var2% expands BEFORE the loop starts, you need here delayed expansion or the call technic (very slow) – jeb Jun 08 '11 at 17:30
0

This works for me:

@echo off
SETLOCAL EnableDelayedExpansion

FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ paths.txt"`) do (
set var=%%a
set var=!var:*:=!
echo !var!
)
ENDLOCAL
Andrew Cooper
  • 32,176
  • 5
  • 81
  • 116
  • I introduced the delayed toggling technic, as in your code you will lose all `!` and sometimes also the `^` – jeb Jun 08 '11 at 17:32