Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Windows CMD - set within for loop is not working

Tags:

batch-file

cmd

I want to write batch file which will loop through all directories containing backup directory and remove files older than X days within it. On computer which I want run my script there's no "forfile" command. There's no PowerShell, so CMD or VBScripts seems to be only way of accomplishing this task.

Currently I have problem with "set" statement - it seems that when I'm calling %checkpath% I didn't receive expected folder.

rem we will memorize current directory
pushd %cd%
set folder="C:\Documents and Settings\myname\Desktop"
cd %folder%
rem loop only folders with five chars within their names (unfortunately on less also
for /D %%g in (?????) DO (
    set checkpath="%cd%\%%g\backup"
    if exist %checkpath% (
        for %%a in ('%%g\backup\*.*') do (
        set FileDate=%%~ta
        set FileDate=%%FileDate:~0,10%%
        rem here I want to compare file modification data with current date
        )
    )
popd
pause
like image 751
matandked Avatar asked Dec 16 '22 19:12

matandked


2 Answers

You need to use delayed expansion to read a variable that you have set inside a for loop.

Try this instead

setlocal enabledelayedexpansion
rem we will memorize current directory
pushd %cd%
set folder="C:\Documents and Settings\myname\Desktop"
cd %folder%
rem loop only folders with five chars within their names (unfortunately on less also
for /D %%g in (?????) DO (
    set checkpath="%cd%\%%g\backup"
    if exist !checkpath! (
        for %%a in ('%%g\backup\*.*') do (
        set FileDate=%%~ta
        set FileDate=!%FileDate:~0,10%!
        rem here I want to compare file modification data with current date
        )
    )
popd
pause

Replacing the %'s with !'s on variables you have created will signal it to use delayed expansion instead.

like image 65
Bali C Avatar answered Feb 12 '23 15:02

Bali C


Bali's answer has a slight mistake. The second set filedate is incorrect, otherwise his is fine, but may not work if you do not have delayed expansion enabled. I fixed his mistake and showed you how to ensure delayed expansion is enabled. I have also made some other changes:

::This command will ensure that the delayed expansion, i.e. the "!"s below, 
::  will work.  Unfortunately, it also means you loose the results of any
::  "set" commands as soon as you execute the "endlocal" below.
setlocal ENABLEDELAYEDEXPANSION

::you might want
::set "folder=%USERPROFILE%\Desktop"
set "folder=C:\Documents and Settings\myname\Desktop"

rem we will memorize current directory
::If you ran this code with the current directory set to a directory on
::a drive other than C:, your previous code would not have worked to
:: change to your desired target directory.  this slight change fixes that.
pushd "%folder%"

rem loop only folders with five chars within their names - unfortunately on less also
::Use capitals for your loop variables.  The var names are case sensitive, and 
::using capitals ensures there is no confusion between the var names and ~modifiers
for /D %%G in ( ????? ) DO (
    set checkpath="%CD%\%%G\backup"
    if exist !checkpath! (
        for %%A in ('%%G\backup\*.*') do (
            set FileDate=%%~tA
            set FileDate=!FileDate:~0,10!
            rem here I want to compare file modification data with current date
        )
)
popd
endlocal
pause

But, you don't need the "setlocal" or delayed expansion if you write it like this:

::you might want
::set "folder=%USERPROFILE%\Desktop"
set "folder=C:\Documents and Settings\myname\Desktop"

rem we will memorize current directory
::If you ran this code with the current directory set to a directory on
::a drive other than C:, your previous code would not have worked to
:: change to your desired target directory.  this slight change fixes that.
pushd "%folder%"

rem loop only folders with five chars within their names - unfortunately on less also
for /D %%G in ( ????? ) DO (
    if exist "%%~G\backup" (
        for %%A in ('%%~G\backup\*.*') do (
            for /F "usebackq" %%T in ( '%%~tA' ) do (
                echo File date is %%T, todays date is %DATE%
            )
        )
)
popd
pause
like image 30
David I. McIntosh Avatar answered Feb 12 '23 15:02

David I. McIntosh