windows batch, setting a variable inside a nested loop - windows

I have the below batch that reads data from a text file, the problem is in the inner loop; it should get the lat created file in the destination folder, and it just gets nothing!
here's my code:
:: Delete Files from folder
#echo off
:: Delete Files from folder
echo y | del "E:\HIS_Data_Consolidation\HIS_Backups\*.bak"
echo Deleting previous bak files...
set destdir=E:\HIS_Data_Consolidation\HIS_Backups
setlocal
FOR /F "tokens=1,2,3 delims=," %%G IN (clinics.txt) DO (
pushd "%%G"
for /F "tokens=*" %%a in ('dir *.* /b /a-d /o:e 2^>NUL') do (
set lfile=%%a
)
echo copying "%%G\%lfile%" to "%destdir%" ,,,%%H
copy /y "%%G\%lfile%" "%destdir%
E:
cd "%destdir%
E:\HIS_Data_Consolidation\HIS_Backups\unrar.exe e "%destdir%/%lfile%"
echo y | del "E:\HIS_Data_Consolidation\HIS_Backups\*.rar"
echo Deleting RAR file...
SET v_test=%lfile%
SET v_result=%v_test:rar=bak%
ren "%v_result%" "%%I"
echo Ready ...
popd
)
pause
appreciate you help.
thanks.

If you'are using a set inside for body you'll need enabledelayedexpansion:
http://www.robvanderwoude.com/variableexpansion.php
edit:
:: Delete Files from folder
#echo off
:: Delete Files from folder
echo y | del "E:\HIS_Data_Consolidation\HIS_Backups\*.bak"
echo Deleting previous bak files...
set destdir=E:\HIS_Data_Consolidation\HIS_Backups
setlocal enabledelayedexpansion
FOR /F "tokens=1,2,3 delims=," %%G IN (clinics.txt) DO (
pushd "%%G"
for /F "tokens=*" %%a in ('dir *.* /b /a-d /o:e 2^>NUL') do (
set lfile=%%a
)
echo copying "%%G\!lfile!" to "!destdir!" ,,,%%H
copy /y "%%G\!lfile!" "!destdir!"
E:
cd "!destdir!"
E:\HIS_Data_Consolidation\HIS_Backups\unrar.exe e "!destdir!/!lfile!"
echo y | del "E:\HIS_Data_Consolidation\HIS_Backups\*.rar"
echo Deleting RAR file...
SET v_test=!lfile!
SET v_result=!v_test:rar=bak!
ren "!v_result!" "%%I"
echo Ready ...
popd
)
endlocal
pause

#npocmaka
Thank you! You solved my problem I was working on for hours!
I had a similar problem.
I was using a nested for loop and tried to split the for loop into another batch file, but didn't work. So I used 'npocmaka's advice:
This is the batch being called which is inside another for loop.
#ECHO OFF
SET dir=%~1
SET suf=%~2
ECHO IN dir:%dir%
ECHO IN suf:%suf%
PAUSE
SET /A count=1
SETLOCAL EnableDelayedExpansion
pushd %dir%
FOR /R . %%A IN (*.%suf%) DO (
ECHO File: %%~nxA count:!count!
PAUSE
REN %%~nxA !count!.txt
CALL :increment RESULT count
)
popd
ENDLOCAL
:increment
SET /A count+=1

Related

Batch file: Deleting folders after for loop

This is what i have right now. If I run this script, loop never ends and run forever.
I tried to delete a folder in kmz folder after moving a file inside kmz folder's folder; however, it wont delete a folder inside the kmz folder. I think this is why my batch file is running forever.
any help??
setlocal enableextensions enabledelayedexpansion
:loop
IF EXIST D:\kmz\*.* (
FOR /f "delims=" %%a IN ('dir /b /s /a-d "D:kmz\*.*" ') do (
FOR %%b IN ("%%~dpa.") do (
REN "%%a" "%%~nb.*"
move %%b\* D:\renamed
del %%b
goto loop2
)
)
)
:loop2
IF EXIST D:\renamed\*.* (
for /R D:\renamed %%G in (*.*) do (
ogr2ogr -f "ESRI Shapefile" "D:\shapefile\%%~nG_boundary.shp" "%%G"
move %%G D:\Photos\%%~nG
goto transfering
)
)
:transfering
IF EXIST D:\shapefile\*.shp (
for /R D:\shapefile %%K in (*.*) do (
set "filename=%%~nK"
set "first5=!filename:~0,5!"
move %%K D:\Photos\!first5!
echo !date!-!time! %%K is created >> D:\Photos\!first5!\log.txt
)
)
goto loop
this is my second try:
setlocal enableextensions enabledelayedexpansion
:loop
FOR /f "delims=" %%a IN ('dir /b /s /a-d "D:kmz\*.*" ') do (
FOR %%b IN ("%%~dpa.") do (
IF EXIST %%a (
REN "%%a" "%%~nb.*"
move %%b\* D:\renamed
rmdir %%~dpa
goto loop2
)
)
)
:loop2
IF EXIST D:\renamed\*.* (
for /R D:\renamed %%G in (*.*) do (
ogr2ogr -f "ESRI Shapefile" "D:\shapefile\%%~nG_boundary.shp" "%%G"
move %%G D:\Photos\%%~nG
goto transfering
)
)
:transfering
IF EXIST D:\shapefile\*.shp (
for /R D:\shapefile %%K in (*.*) do (
set "filename=%%~nK"
set "first5=!filename:~0,5!"
move %%K D:\Photos\!first5!
echo !date!-!time! %%K is created >> D:\Photos\!first5!\log.txt
)
)
goto loop
I was able to delete a folder from D:\kmz, but loops wont stop.
I this this output is the reason...
C:\>FOR /F "delims=" %a IN ('dir /b /s /a-d "D:kmz\*.*" ') do (FOR %b IN ("%~dpa.") do (IF EXIST %a (
REN "%a" "%~nb.*"
move %b\* D:\renamed
rmdir %~dpa
goto loop2
) ) )
File Not Found
To stop your loop, try setting loop as a variable with a value of one, and code it so that every time you run the command it takes away one from loop. Then say if the loop variable equals 0, go to another part which has the directory of your file and the delete command. I hope this works.

Use a Batch File to list files and allow the user to select which file to copy into a new destination

I am a newbie to Windows Scripting.
I am trying to list some txt files in several sub directories & want to copy a user selected file to a new destination. Please note that the file name is unique in different locations.
I got the first part to work (Listing out the files & locations) using the following script, but I am unable to copy the selected file to the new location.
#ECHO OFF
SET index=1
SETLOCAL ENABLEDELAYEDEXPANSION
SET FFPath="C:\Scripts - Backup Server\DKXpress_bkp"
SET NewPath=C:\DKServer
ECHO Recursively searching %FFPath%
echo.
FOR /F "delims=" %%f in ('DIR %FFPath%\*.txt /a:-d /s /b') DO (
SET file!index!=%%f
ECHO !index! - %%f
SET /A index=!index!+1
)
SETLOCAL DISABLEDELAYEDEXPANSION
SET /P selection="select file by number:"
SET file%selection% >nul 2>&1
IF ERRORLEVEL 1 (
ECHO invalid number selected
EXIT /B 1
)
SET NewFile=file%selection%
ECHO Copying %NewFile% to %NewPath%
ECHO.
COPY /Y "%NewFile%" "%NewPath%"
ECHO.
PAUSE
I think I am doing this part wrong
SET NewFile=file%selection%
Thank you all in advance
You don't need to set an index variable or delayed expansion, if you let Find do the work for you:
#Echo Off
Set "FFPath=C:\Scripts - Backup Server\DKXpress_bkp"
Set "NewPath=C:\DKServer"
Echo Recursively searching %FFPath%
Echo=
For /F "Delims==" %%A In ('"Set File[ 2>Nul"') Do Set "%%A="
For /F "Tokens=1* Delims=]" %%A In (
'"Dir /B/S/A-D-S-L "%FFPath%\*.txt" 2>Nul|Find /N /V """') Do (
Echo %%A] %%B
Set "File%%A]=%%B"
)
Echo=
Set /P "#=Select file by number: "
Echo=
For /F "Tokens=1* Delims==" %%A In ('"Set File[%#%] 2>Nul"') Do (
Echo Copying %%B to %NewPath%&Echo=
Copy /Y "%%B" "%NewPath%"
GoTo :End
)
Echo Invalid number selected
:End
Echo=
Pause
You need to use delayed expansion to get the file name assigned to the variable correctly.
SET NewFile=!file%selection%!
Remove the setlocal to disable delayed expansion.
You can try something like that :
#ECHO OFF
:Main
cls
SET index=1
SETLOCAL ENABLEDELAYEDEXPANSION
SET FFPath="C:\Scripts - Backup Server\DKXpress_bkp"
SET "NewPath=C:\DKServer"
ECHO Recursively searching %FFPath%
echo.
FOR /F "delims=" %%f in ('DIR %FFPath%\*.txt /a:-d /s /b') DO (
SET filepath[!index!]=%%f
ECHO [!index!] - %%~nxf - %%f
SET /A index=!index!+1
)
echo(
echo select file by number :
set /p Input=""
For /L %%i in (1,1,%index%) Do (
If "%INPUT%" EQU "%%i" (
ECHO Copying "!filepath[%%i]!" to "!NewPath!"
COPY /Y "!filepath[%%i]!" "!NewPath!"
)
)
echo Copying another file ? (Y = Yes or N = No) ?
set /p input2=""
If /I "!input2!"=="Y" (
goto :Main
) else (
goto :eof
)

Batch parameters with spaces for loop recursive move

I am trying to put a batch together to move all zip files back one directory from the current directory in a recursive move where I specify the search directory from the parent.
In example, the current directory is download and the sub to recursive search is a command line parameter.
I then want to move the *.zip back one directory from download. I don't want to search in any other directory other than the one I specify.
>movezipdir junk 2009
This outputs junk 2009. Then junk was unexpected at this time.
Here's what I have but the for loop doesn't like the variable with spaces...
#echo off
IF %1.==. GOTO No1
set DirName=%*
echo %DirName%
For /d %DirName% in ( *.* ) do (
For /d %%e in (""%DirName%"\*") do (
rem move /Y "%%e\*.zip" "%CD%\.."
echo %DirName%
rem rd /S /Q "%%e"
)
rem rd /S /Q %DirName%
)
GOTO End1
:No1
ECHO No Directory Specified
GOTO End1
:End1
It would be great if someone could point me in the right direction. Thanks. Ken
#echo off
rem :: check if the args is not nul
if [%1] == [] (
goto error
) else (
for /f "usebackq tokens=1*" %%i in ('echo %*') do (
set "dirname=%%~i"
)
)
rem check if the specified args correspond to a directory
if exist "%dirname%\nul" echo %dirname% it's a directory || goto error
set /a c=1
setlocal EnableDelayedExpansion
for /f "tokens=* delims=" %%a in ('dir /b /s /a-d "%dirname%\*.txt"') do (
rem usage: move [{/y | /-y}] [Source] [Target]
rem https://technet.microsoft.com/en-us/library/cc772528.aspx
rem http://ss64.com/nt/move.html
rem %cd% here are redundant because when target are omitted,
rem the target are always the current directory
echo move /-y "%%a" "%cd%"
rem break loop after 5 iterations.
rem You can remove it if the test are Okay
if [!c!] equ [5] goto break_loop
set /a c+=1
)
:break_loop
rem usage: RD [/S] [/Q] [drive:]path
echo rd /s /q %dirname%
exit /b 0
:error
echo Error: No directory specified or invalid arguments
echo Usage: %~0 ^<full path of the directorys^>
echo Example: %~0 c:\user\janne\MyDocuments
exit /b 0

Windows batch file to find duplicates in a tree

I need a batch file ( Windows CMD is the interpreter, a .bat ) to do this type of task:
1) Search through a folder and its subfolders
2) Find files with the same filename and extension ( aka duplicates )
3) Check if they have the same size
4) If same name + same size, echo all the files except the first one ( practically I need to delete all except one copy )
Thanks for any type of help
This is only an initial script, just for check the files, in a folder and its subfolders, and their size:
#Echo off
Setlocal EnableDelayedExpansion
Set Dir=C:\NewFolder
For /r "%Dir%" %%i in (*) do (
Set FileName=%%~nxi
Set FullPath=%%i
Set Size=%%~zi
Echo "!FullPath!" - SIZE: !Size!
)
Echo.
Pause
This script does what you ask. Just set the ROOT variable at the top to point to the root of your tree.
#echo off
setlocal disableDelayedExpansion
set root="c:\test"
set "prevTest=none"
set "prevFile=none"
for /f "tokens=1-3 delims=:" %%A in (
'"(for /r "%root%" %%F in (*) do #echo %%~znxF:%%~fF:)|sort"'
) do (
set "currTest=%%A"
set "currFile=%%B:%%C"
setlocal enableDelayedExpansion
if !currTest! equ !prevTest! echo "!currFile!"
endlocal
set "prevTest=%%A"
)
But you can make the test more precise by using FC to compare the contents of the files. Also, you can incorporate the DEL command directly in the script. The script below prints out the commands that would delete the duplicate files. Remove the ECHO before the DEL command when you are ready to actually delete the files.
#echo off
setlocal disableDelayedExpansion
set root="c:\test"
set "prevTest=none"
set "prevFile=none"
for /f "tokens=1-3 delims=:" %%A in (
'"(for /r "%root%" %%F in (*) do #echo %%~znxF:%%~fF:)|sort"'
) do (
set "currTest=%%A"
set "currFile=%%B:%%C"
setlocal enableDelayedExpansion
set "match="
if !currTest! equ !prevTest! fc /b "!prevFile!" "!currFile!" >nul && set match=1
if defined match (
echo del "!currFile!"
endlocal
) else (
endlocal
set "prevTest=%%A"
set "prevFile=%%B:%%C"
)
)
Both sets of code may seem overly complicated, but it is only because I have structured the code to be robust and avoid problems that can plague simple solutions. For example, ! in file names can cause problems with FOR variables if delayed expansion is enabled, and = in file name causes a problem with npocmoka's solution.
#echo off
setlocal
for /f "tokens=1 delims==" %%# in ('set _') do (
set "%%#="
)
for /r %%a in (*.*) do (
if not defined _%%~nxa%%~za (
set "_%%~nxa%%~za=%%~fa"
) else (
echo %%~fa
)
)
endlocal

for command is executed only for the first value when a label is inside

I have the script
for /f "delims=" %%i in ('dir "%folder%*.txt" /b /s') do (
set s=%%i
set s=!s:%folder%=!
set new_s=!s:\=!
if "x!new_s!" NEQ "x!s!" (
:ProcessListSource
For /f "tokens=1* delims=\" %%A in ("!s!") do (
if "%%A" NEQ "" (
if "!Folder1!" NEQ "" (
Set Folder1=!Folder1!\!Name!
)else (
Set Folder1=!Name!
)
Set Name=%%A
)
if "%%B" NEQ "" (
set s=%%B
goto :ProcessListSource
)
)
echo Folder is: !Folder1!
echo Name is: !Name!
echo ---------------------
) else (
echo Not a folder !s!
)
)
but it does not work as I would have expected:
The first for is executed only once and also the last echo is printed on the screen.
Given a folder I need the files from subfolders without the given folder and than split them into the folder and file
Ex: folder=C:\test
The for would give me the file C:\test\test1\test2\t.txt
And I need test1\test2 and t.txt
GOTO breaks your FOR /F \ IF context and they can be executed only once.
More simple example:
#echo off
for /l %%S in (1=1=5) do (
echo %%S
goto :inner_label
rem
:inner_label
rem
)
This will print only 1 . Do you really need the GOTO here?
When the parser reads your code, all the code inside your for loop is "considered" as only one command that is readed, parsed and executed. As stated in the npocmaka answer, any goto call takes you out of this "line" of code, ending the process of the for loop.
This is a alternative. Use pushd + xcopy /l /s commands to generate a list of the relative paths of the files.
#echo off
setlocal enableextensions disabledelayedexpansion
set "folder=%cd%"
pushd "%folder%"
for /f "delims=" %%a in ('xcopy /l /s /y * "%temp%"^|findstr /vbr /c:"[0-9]"'
) do for /f "delims=: tokens=1,*" %%b in ("%%~a") do (
echo [%%c] [%%~nxa]
)
popd

Resources