0

Am trying to use substring manipulation within a FOR loop and I can't get it to work for love nor money. I've been told that we can't use substring manipulation on a loop variable (%%f etc), so you have to set another variable to equal the loop (set MyVariable=%%f) and then use a substring option to work on this decendent (set MyOtherVar=%MyVariable:~0,-3%). However when echoing these variables only the loop variable is set/non-null.

Here's the code I'm currently using.

@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
SET OutPref="373137#"
SET OutSuf1="#Window Clean POD "
SET OutSuf2="#1520755.pdf"
SET MatchStr=@mydomain.com
cd c:\Oscar\Scripts\FileNamer\Inbound\
for /f "tokens=*" %%f in ('dir /b *.pdf') do (
    c:\Oscar\Scripts\FileNamer\pdftotext.exe -q %%f
    set InPdfVer=%%f
    set InTxtVer=%InPdfVer:~0,-3%txt
    echo Loop Val= %%f
    echo InPdfVer= %InPdfVer%
    echo InTxtVer= %InTxtVer%
    pause
    set InAddLine=findstr %MatchStr% %InTxtVer%

    set stemp=%InAddLine%
    set pos=0
    :loop
    set /a pos+=1
    echo %stemp%|findstr /b /c:"%MatchStr%" >NUL
    if errorlevel 1 (
            set stemp=%stemp:~1%
            if defined stemp GOTO loop
            set pos=0
            )

    set /a pos-=3
    call set StoreNo=%InAddLine:~%pos%,-25%
    call:getvalue C:\Oscar\Scripts\FileNamer\StoreList.inf %StoreNum% StoreName
    set OutFile=%OutPerf%%StoreNo%%OutSuf1%%StoreName%%OutSuf2%
    move %%f c:\Oscar\Scripts\FileNamer\Outbound\%OutFile%

)
cd c:\Oscar\Scripts\FileNamer\
exit 0

:getvalue
rem This function reads a value from a file and stored it in a variable
rem %1 = name of file to search in
rem %2 = search term to look for
rem %3 = variable to place search result
FOR /F "tokens=1,2* delims==" %%i in ('findstr /b /l /i %~2= %1') DO set %~3=%%~j
goto:eof

Hope this makes sense, can try and explain it. Quite likely the bottom part doesnt work either but didnt get that far!

Thanks for any thoughts either way, as a general overview the script is supposed to take PDF files in the incoming folder, convert them to text, search for an email address in that file, look that email address in an external list and then move the PDF file (renaming the file with an aggreed convention in the process) and then move onto the next file, in a loop, until the end of the matching files.

Kind regards, Oscar

OK so the rest of it seems to what what it should now but I still can't get this substring to set, I just end up with the whole string in the decendent variable. Here's the new code (please excuse the pauses and echos used for troubleshooting).

@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
SET OutPref=373137#
SET OutSuf1=#Window Clean POD 
SET OutSuf2=#1520755.pdf
SET MatchStr=@mydomain.com
cd c:\Oscar\Scripts\FileNamer\Inbound\
for /f "tokens=*" %%f in ('dir /b *.pdf') do (
    c:\Oscar\Scripts\FileNamer\pdftotext.exe -q %%f
    set InPdfVer=%%f
    call set InTxtVer=!InPdfVer:~0,-3!txt
    for /f "tokens=*" %%x in ('findstr !MatchStr! !InTxtVer!') do set InAddLine=%%x
    call:getpos
    echo !pos!
pause
    call set StoreNo=!InAddLine:~!pos!,-25!
    call:getvalue C:\Oscar\Scripts\FileNamer\StoreList.inf !StoreNum! StoreName
echo OutPerf !OutPref!
echo StoreNo !StoreNo!
echo OutSuf1 !OutSuf1!
echo StoreName !StoreName!
echo Outsuf2 !OutSuf2!
    set OutFile=!OutPerf!!StoreNo!!OutSuf1!!StoreName!!OutSuf2!
echo %%f !OutFile!
pause
REM move %%f c:\Oscar\Scripts\FileNamer\Outbound\!OutFile!
)
cd c:\Oscar\Scripts\FileNamer\
exit /b

:getpos
set stemp=!InAddLine!
set pos=0
:loop
set /a pos+=1
echo !stemp!|findstr /b /c:"!MatchStr!" >NUL
if errorlevel 1 (
        set stemp=!stemp:~1!
        if defined stemp GOTO loop
        set pos=0
        )
set /a pos-=3
goto:eof

:getvalue
rem This function reads a value from a file and stored it in a variable
rem %1 = name of file to search in
rem %2 = search term to look for
rem %3 = variable to place search result
FOR /F "tokens=1,2* delims==" %%i in ('findstr /b /l /i %~2= %1') DO set %~3=%%~j
goto:eof
Xeotech
  • 1
  • 3
  • 4
    You need to look up Delayed Expansion. The variables set within for block should be referenced using `!` not `%`, i.e. `!InPdfVer:~0,-3!` etc. – Compo Mar 07 '17 at 13:39
  • 3
    Also - you cannot use a label like `loop` within a code-block (parenthesised series of commands) – Magoo Mar 07 '17 at 13:46
  • A ha! Had looked up substring manipulation for ages and couldnt see the issue and it turns out it's the delayed expansion that's messed it up. I take it not expanding %%f type variables in advance of being referenced is sort of a given, seeing as the variable needs to differ per itteration of the for loop. – Xeotech Mar 07 '17 at 14:24
  • OK thanks for your tips, new version written up, put the GOTO cycle after the main FOR loop which seems to work as far as I can tell. Also changed the set=findstr x y for for; /f "tokens=*" %%x in ('findstr !MatchStr! !InTxtVer!') do set InAddLine=%%x, again which seems to work. Any thoguhts on the "call set InTxtVer=!InPdfVer:~0,-3!txt" line, tried it with and without a call. Thanks for your help! – Xeotech Mar 07 '17 at 15:17
  • 1
    `set "InTxtVer=!InPdfVer:~0,-3!txt"` and `call set "InTxtVer=%%InPdfVer:~0,-3%%txt"` are equivalent. However, I'd use `set "InTxtVer=%%~nf.txt"`, see https://ss64.com/nt/syntax-args.html – JosefZ Mar 07 '17 at 15:42
  • Sorry, wrong substring, the one above is working, it's the one that uses a variable as the 'start char' command input. – Xeotech Mar 07 '17 at 15:42
  • call set StoreNo=!InAddLine:~!pos!,-25! – Xeotech Mar 07 '17 at 15:43
  • Thanks for your input @JosefZ some very useful stuff I hand't encountered yet! – Xeotech Mar 07 '17 at 15:46
  • 2
    Your `call set StoreNo=!InAddLine:~!pos!,-25!` must be `call set StoreNo=%%InAddLine:~!pos!,-25%%`. I suggest you to read [this answer](http://stackoverflow.com/questions/10166386/arrays-linked-lists-and-other-data-structures-in-cmd-exe-batch-script/10167990#10167990) – Aacini Mar 07 '17 at 15:49
  • It certainly must! Thanks for your help! I've read your very thorough post on a slightly related matter but yet to see why it has to use %% before and after. More batch file homework! Next problem coming up shortly no doubt! Thanks very much for the pointers, it's not for want of looking, it's just such a complicated syntax at times! – Xeotech Mar 07 '17 at 16:02
  • Nope it's pretty much working, am awaiting more example files from the requestor to test it thoroughly but so far so good. Thanks to all for your help! Will stick the final version in as an answer in case it can help anyone else making the same operations. – Xeotech Mar 07 '17 at 17:15

1 Answers1

0

Thanks all for your inputs, here's the finished script with a few more updates.

Makes use of pdftotext.exe as part of the freeware xpdf suite (please donate as it's a great utility) and in this case some lookup files that help resolve a site number to its description. In the format of 001=My Town

I totally failed to get a workable way to pad 2 digit site codes with a leading 0 to make all sites 3 digits but ended up doing the same thing with another lookup file!

I hope this is of some use to someone else!

@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
SET OutPref=373137#
SET OutSuf1=#My Text 
SET OutSuf2=#1520755.pdf
SET MatchStr=@mydomain.com
SET BaseDir=C:\myfolder\
SET LogFile=C:\myfolder\FileNamer.log
SET InFolder=C:\myfolder\Inbound\
SET OutFolder=C:\myfolder\Outbound\
SET StoreList=C:\myfolder\StoreList.inf
SET StoreNoConv=C:\myfolder\StoreNoConv.inf

echo Starting Run %TIME% %DATE% >> %LogFile%
echo Starting Run %TIME% %DATE%
cd %InFolder%
for /f "tokens=*" %%f in ('dir /b *.pdf') do (
    %BaseDir%pdftotext.exe -q %%f
    set "InTxtVer=%%~nf.txt"
    for /f "tokens=*" %%x in ('findstr !MatchStr! !InTxtVer!') do set InAddLine=%%x
    call:getpos
    call set StoreNo=%%InAddLine:~!pos!,-25%%
    echo Now Renaming Store No !StoreNo!
    call:getvalue %StoreList% !StoreNo! StoreName
    call:getvalue %StoreNoConv% !StoreNo! ThreeDigitNo
    set OutFile=!OutPref!Store!ThreeDigitNo!!OutSuf1!!StoreName!!OutSuf2!
    echo %%f moved to !OutFile! >> %LogFile%
    move "%%f" "%OutFolder%!OutFile!" >> %LogFile%
    del !InTxtVer!
)

cd %BaseDir%
exit /b



:getpos
set stemp=!InAddLine!
set pos=0
:loop
set /a pos+=1
echo !stemp!|findstr /b /c:"!MatchStr!" >NUL
if errorlevel 1 (
        set stemp=!stemp:~1!
        if defined stemp GOTO loop
        set pos=0
        )
set /a pos-=4
goto:eof

:getvalue
rem This function reads a value from a file and stores it in a variable
rem %1 = name of file to search in
rem %2 = search term to look for
rem %3 = variable to set search result under
FOR /F "tokens=1,2* delims==" %%i in ('findstr /b /l /i %~2= %1') DO set %~3=%%~j
goto:eof
Xeotech
  • 1
  • 3