Link to home
Start Free TrialLog in
Avatar of ReneGe
ReneGeFlag for Canada

asked on

Batch File: SET SourceFolder=!SourceFolder:%DestBasePath%=!

Hi there,

In the following script, the line:
SET SourceFolder=!SourceFolder:%DestBasePath%=!

Does not work. I get the following output for that particular command line:
** SourceFolder=SourceFolder:=


SCRIPT TO FIX:
--------------------------------------------------------------------------
@echo off
setlocal enabledelayedexpansion

SET DisplayLines=40
MODE CON: COLS=150 LINES=!DisplayLines!


::SETTING STATIC VARIABLES
      SET CounterPath=0
      FOR /F "tokens=1-3 delims=:. " %%A in ('echo !time!') do set TheTime=%%A.%%B.%%C
      SET TheDate=!date!


::CREATING DATE VARIABLES
      For /f "Tokens=1-3 Delims=-" %%A in ('Echo !date!') do (set Year=%%A&& Set Month=%%B&& Set Day=%%C)


::READING INI FILES
      for /F "tokens=1,2 delims=^=" %%A in (Settings.ini) do SET Setting.ini_%%A=%%B
      for /F "tokens=1,2 delims=^>" %%A in (Paths.ini) do (
            SET /a CounterPath=!CounterPath! + 1
            SET SourceBasePath!CounterPath!=%%A
            SET DestBasePath!CounterPath!=%%B
      )


::SETUP HAS-BEEN FOLDER
      SET HasBeenFolder=!Setting.ini_HasBeenFolder!
      IF not exist !HasBeenFolder!  md !HasBeenFolder!
      IF not exist !HasBeenFolder!  ECHO.&&ECHO HAS-BEEN BASE FOLDER COULD NOT BE AUTOMATICALLY CREATED. PLEASE DO IT MANUALLY&&ECHO.&&PAUSE
      SET HasBeenFolder=!HasBeenFolder!\!Year!&&            IF not exist "!HasBeenFolder!" md "!HasBeenFolder!">NUL
      SET HasBeenFolder=!HasBeenFolder!\!Month!&&            IF not exist "!HasBeenFolder!" md "!HasBeenFolder!">NUL
      SET HasBeenFolder=!HasBeenFolder!\!Day!&&                  IF not exist "!HasBeenFolder!" md "!HasBeenFolder!">NUL
      SET HasBeenFolder=!HasBeenFolder!\!TheTime!&&      IF not exist "!HasBeenFolder!" md "!HasBeenFolder!">NUL


::MOVE HAS-BEENS (FILE DELETED FROM SOURCE OR ABOUT TO BE REPLACED.) TO HAS-BEEN FOLDER.
FOR /L %%A in (1,1,!CounterPath!) do (
            SET SourceBasePath=!SourceBasePath%%A!
            SET DestBasePath=!DestBasePath%%A!
            ::
            FOR /F "delims=!" %%A in ('DIR /a-d /b /s !DestBasePath!') do (
                        ECHO --------------------------------
                        SET FileName=%%~nA%%~xA&& ECHO ** FileName=!FileName!
                        SET FilePath=%%~pA&&      ECHO ** FilePath=!FilePath!
                        ::SETUP DESTINATION FILE INFOS
                              SET DestFileFull=%%~fA&& ECHO ** DestFileFull=!DestFileFull!
                              SET DestFileSize=%%~zA&& ECHO ** DestFileSize=!DestFileSize!
                              SET DestFileDate=%%~tA&& ECHO ** DestFileDate=!DestFileDate!
                        ::SETUP SOURCE INFOS
                              FOR %%A in ("!DestFileFull!") do SET SourceFolder=%%~dA%%~pA
                              SET SourceFolder=!SourceFolder:%DestBasePath%=!
                              ECHO ** SourceFolder=!SourceFolder!
                              IF EXIST !SourceFileFull! (
                                    FOR %%A in ("!SourceFileFull!") do SET SourceFileSize=%%~zA
                                    FOR %%A in ("!SourceFileFull!") do SET SourceFileDate=%%~tA
                                    ECHO ** SourceFileSize=!SourceFileSize!
                                    ECHO ** SourceFileDate=!SourceFileDate!
                                    IF !SourceFileDate! NEQ !DestFileDate! ECHO ** DATE IS NOT THE SAME
                              ) ELSE (
                                    ECHO ** FILE DOES NOT EXIST AT SOURCE
                              )
                  )
      )

PAUSE
exit


Thanks for your help,
Rene
Avatar of Bill Prew
Bill Prew

Yes, you have a problem.  Basically, here is what you have:

FOR /L %%A in (1,1,!CounterPath!) do (
. . .
            SET DestBasePath=!DestBasePath%%A!
. . .
                              SET SourceFolder=!SourceFolder:%DestBasePath%=!

As you can see, you are referencing DetBasePath inside a large FOR loop where it's value was assigned.  As a result you can not reference it with %DestBasePath% as a result.  And sadly, the following does not work:

                              SET SourceFolder=!SourceFolder:!DestBasePath!=!

There's a bit to this script, so I'll study it a bit more and see if there's a way to get the effect you want.

~bp
Not quite sure what you are trying to do there but I presume maybe you mean:
  SET SourceFolder=!SourceFolder:%DestBasePath%!
i.e. not the second =?

Steve
SOLUTION
Avatar of Steve Knight
Steve Knight
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of ReneGe

ASKER

==>dragon-it, This script should get kind of large and I'd rather skip un-necessary "CALL" option if possible.

==>billprew, yes, I tried to acceive: SET SourceFolder=!SourceFolder:!DestBasePath!=! without result, so I tried with the %.

What I'm puzzled, is that I made a test script and this one works with the %

TEST SCRIPT:
-----------------------------------------------------------------------
@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION

SET BaseFolder=C:\Batchfiles
SET NewBaseFolder=C:\TestFolder

FOR /F "DELIMS=" %%A IN ('dir /b *.txt') do set File=%%~fA
SET Destination=!File:%BaseFolder%=!
SET Destination=!NewBaseFolder!!Destination!
echo !Destination!
pause
exit



I'll wait for your solution.

Cheers,
Rene
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
   You have alot of improperly terminated delayed expantion here.  please note that if you use too many delays sometimes you will have issues, reguardless, try te attached script, because all i did was properly terminate all your delayed expantion

Also I know what you are mentioning I haven't tested your looping yet with the fixed delayed expantion however because you weren't inside a delayed expantion I assume the issue was base you werten;t using a CALL, becvause I generally work without a delayed expantion I'm used to haveing to do this to get the effect you want:

CALL SET ThisVariable=%%ThisVariable%ThatVariable%%%

IN YOUR Case I would belivee it would be similar to this:

CALL SET SourceFolder=%%SourceFolder:!DestBasePath!=%%

@ECHO OFF
SETLOCAL EnableDelayedExpansion

SET "DisplayLines=40"
MODE CON: COLS=150 LINES=%DisplayLines%

::SETTING STATIC VARIABLES
	SET "CounterPath=0"
	FOR /F "Tokens=1-3 Delims=:" %%A in ("%TIME: =0%") DO SET "TheTime=%%A.%%B.%%C"
	:: DO you realise this date will be in the format "ddd MM\DD\YYYY" if you are in the NA Region settings..?
	SET "TheDate=%DATE%"
	:: A better Idea would be to use an ISO Date FOR all yrou Date handling.. YYYY-MM-DD Like this
	::SET TheDate=%DATE:~10,4%-%DATE:~4,2%-%DATE:~7,2%
	
::CREATING DATE VARIABLES
	FOR /F "Tokens=1-3 Delims=-" %%A in ("%TheDate%") DO SET "Year=%%A"&SET "Month=%%B"&SET "Day=%%C"
	::Seeing this you have already changed the date format settings in your OS.. ECHo only takes a split second longer but why bother??
	:: FOR my script testing:
	:: ECHO Y=%Year% M=%Month% D=%Day%
	:: SET "Year=%DATE:~10,4%"
	:: SET "Month=%DATE:~4,2%"
	:: SET "Day=%DATE:~7,2%"
	:: ECHO Y=%Year% M=%Month% D=%Day%
	
::READING INI FILES
	::Are you actually expecting to be in the local path where these settings are?
	::Generally speaking you shodul always write full directory paths instead of havingyoru batch file navigate directroies which can cause issues you did not expect!
	FOR /F "Tokens=1,2 Delims=^=" %%A in (C:\Admin\Setting.ini) do SET "Setting.ini_%%A=%%B"
	FOR /F "Tokens=1,2 Delims=^>" %%A in (C:\Admin\Paths.ini) do SET "SourceBasePath!CounterPath!=%%A"&SET "DestBasePath!CounterPath!=%%B"&SET /a CounterPath=!CounterPath!+1
	SET /a CounterPath=%CounterPath%-1
	
::SETUP HAS-BEEN FOLDER
	SET "HasBeenFolder=%Setting.ini_HasBeenFolder%"
	::No need to test FOR the folder the command will DO nothing if the folder already exists
	MD "%HasBeenFolder%">nul
	:: Why not just catch an error level or the error text instead of the following line?
	IF NOT EXIST "%HasBeenFolder%" ECHO.&ECHO HAS-BEEN BASE FOLDER "%HasBeenFolder%" COULD NOT BE AUTOMATICALLY CREATED. PLEASE DO IT MANUALLY&ECHO.&PAUSE
	:: Why not just use THIS command to BEGIN with above and skip your base foler creation??
	SET "HasBeenFolder=%Setting.ini_HasBeenFolder%\%Year%\%Month%\%Day%\%TheTime%"
	:: Why don't you care if there is still a permissions issue??
	MD "%HasBeenFolder%">nul
	
::MOVE HAS-BEENS (FILE DELETED FROM SOURCE OR ABOUT TO BE REPLACED.) TO HAS-BEEN FOLDER.
FOR /L %%A IN (1,1,%CounterPath%) DO (
    SET SourceBasePath=!SourceBasePath%%A!
    SET DestBasePath=!DestBasePath%%A!
    
    FOR /F "delims=!" %%A IN ('DIR /a-d /b /s !DestBasePath!') DO (
        ECHO --------------------------------
        SET FileName=%%~nA%%~xA& ECHO ** FileName=!FileName!
        SET FilePath=%%~pA&      ECHO ** FilePath=!FilePath!
        ::SETUP DESTINATION FILE INFOS
        SET DestFileFull=%%~fA& ECHO ** DestFileFull=!DestFileFull!
        SET DestFileSize=%%~zA& ECHO ** DestFileSize=!DestFileSize!
        SET DestFileDate=%%~tA& ECHO ** DestFileDate=!DestFileDate!
        ::SETUP SOURCE INFOS
        FOR %%A IN ("!DestFileFull!") DO (
			SET SourceFolder=%%~dA%%~pA
			SET SourceFolder=!SourceFolder:%DestBasePath%=!
			ECHO ** SourceFolder=!SourceFolder!
			IF EXIST !SourceFileFull! (
                FOR %%A IN ("!SourceFileFull!") DO (
					SET SourceFileSize=%%~zA
                    FOR %%A IN ("!SourceFileFull!") DO (
						SET SourceFileDate=%%~tA
                        ECHO ** SourceFileSize=!SourceFileSize!
                        ECHO ** SourceFileDate=!SourceFileDate!
                        IF !SourceFileDate! NEQ !DestFileDate! (
							ECHO ** DATE IS NOT THE SAME
						) ELSE (
                            ECHO ** FILE DOES NOT EXIST AT SOURCE
						)
					)
                )
			)
		)
    )
)
PAUSE

ENDLOCAL
GOTO :EOF

Open in new window

I noticed you never created  SourceFileFull variable, was that intentional?

Could you share some text of what this script is intended to do, I suspect there may be simplere ways to accomplish it.

~bp
Also, not sure I understand this line:

   FOR /F "delims=!" %%A in ('DIR /a-d /b /s !DestBasePath!') do (

This appears to indicate that you have filenames with an exclamation point in the name (or path of), but that seems like an odd character to have in a filename?

I'm in the process of doing a bit of a rewrite of your original code just to give you some ideas, but have run into a couple of pieces that I didn't understand.

~bp
Avatar of ReneGe

ASKER

==>billprew, !DestBasePath!' is a variable containing the destination path. I also see that SourceFileFull was not defined like you mentionned. so... I'll be back...

==>QCubed, thanks for your script analyse and suggestions, I will review it and provide you with feedback.

==>Steve, Thanks for your feedback

Cheers,
Rene
Avatar of ReneGe

ASKER

billprew,

Here, I added "SourceFileFull". However, "SET SourceFolder=!SourceFolder:%DestBasePath%=!" is defined before "SourceFileFull" so I sill have an issue with defining  "SET SourceFolder=!SourceFolder:%DestBasePath%=!"

Cheers,
Rene


@echo off
setlocal enabledelayedexpansion

SET DisplayLines=40
MODE CON: COLS=150 LINES=!DisplayLines!


::SETTING STATIC VARIABLES
      SET CounterPath=0
      FOR /F "tokens=1-3 delims=:. " %%A in ('echo !time!') do set TheTime=%%A.%%B.%%C
      SET TheDate=!date!


::CREATING DATE VARIABLES
      For /f "Tokens=1-3 Delims=-" %%A in ('Echo !date!') do (set Year=%%A&& Set Month=%%B&& Set Day=%%C)


::READING INI FILES
      for /F "tokens=1,2 delims=^=" %%A in (Settings.ini) do SET Setting.ini_%%A=%%B
      for /F "tokens=1,2 delims=^>" %%A in (Paths.ini) do (
            SET /a CounterPath=!CounterPath! + 1
            SET SourceBasePath!CounterPath!=%%A
            SET DestBasePath!CounterPath!=%%B
      )


::SETUP HAS-BEEN FOLDER
      SET HasBeenFolder=!Setting.ini_HasBeenFolder!
      IF not exist !HasBeenFolder!  md !HasBeenFolder!
      IF not exist !HasBeenFolder!  ECHO.&&ECHO HAS-BEEN BASE FOLDER COULD NOT BE AUTOMATICALLY CREATED. PLEASE DO IT MANUALLY&&ECHO.&&PAUSE
      SET HasBeenFolder=!HasBeenFolder!\!Year!&&            IF not exist "!HasBeenFolder!" md "!HasBeenFolder!">NUL
      SET HasBeenFolder=!HasBeenFolder!\!Month!&&            IF not exist "!HasBeenFolder!" md "!HasBeenFolder!">NUL
      SET HasBeenFolder=!HasBeenFolder!\!Day!&&                  IF not exist "!HasBeenFolder!" md "!HasBeenFolder!">NUL
      SET HasBeenFolder=!HasBeenFolder!\!TheTime!&&      IF not exist "!HasBeenFolder!" md "!HasBeenFolder!">NUL


::MOVE HAS-BEENS (FILE DELETED FROM SOURCE OR ABOUT TO BE REPLACED.) TO HAS-BEEN FOLDER.
FOR /L %%A in (1,1,!CounterPath!) do (
            SET SourceBasePath=!SourceBasePath%%A!
            SET DestBasePath=!DestBasePath%%A!
            ::
            FOR /F "delims=!" %%A in ('DIR /a-d /b /s !DestBasePath!') do (
                        ECHO --------------------------------
                        SET FileName=%%~nA%%~xA&& ECHO ** FileName=!FileName!
                        SET FilePath=%%~pA&&      ECHO ** FilePath=!FilePath!
                        ::SETUP DESTINATION FILE INFOS
                              SET DestFileFull=%%~fA&& ECHO ** DestFileFull=!DestFileFull!
                              SET DestFileSize=%%~zA&& ECHO ** DestFileSize=!DestFileSize!
                              SET DestFileDate=%%~tA&& ECHO ** DestFileDate=!DestFileDate!
                        ::SETUP SOURCE INFOS
                              FOR %%A in ("!DestFileFull!") do SET SourceFolder=%%~dA%%~pA
                              SET SourceFolder=!SourceFolder:%DestBasePath%=!
                              SET SourceFileFull=!SourceFolder!!FileName!
                              ECHO ** SourceFolder=!SourceFolder!
                              IF EXIST !SourceFileFull! (
                                    FOR %%A in ("!SourceFileFull!") do SET SourceFileSize=%%~zA
                                    FOR %%A in ("!SourceFileFull!") do SET SourceFileDate=%%~tA
                                    ECHO ** SourceFileSize=!SourceFileSize!
                                    ECHO ** SourceFileDate=!SourceFileDate!
                                    IF !SourceFileDate! NEQ !DestFileDate! ECHO ** DATE IS NOT THE SAME
                              ) ELSE (
                                    ECHO ** FILE DOES NOT EXIST AT SOURCE
                              )
                  )
      )

PAUSE
exit



==> This appears to indicate that you have filenames with an exclamation point in the name (or path of),
==> but that seems like an odd character to have in a filename?

Are there actually exclamation points in the filenames?

~bp
Avatar of ReneGe

ASKER

No, the explamation points are to define what ever is in between them as a variable.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of ReneGe

ASKER

==> billprew, now I get the miss-comminucation, ! is not a file delemiter and effectivly will screw up the rest. This was a finger glitch from my part.

==> QCubed I have reviewed your suggestions and this was very edicationnal.
Are you saying that with the following, I canextract date with whatever Windows date format?
%DATE:~10,4%-%DATE:~4,2%-%DATE:~7,2%

-------------------------------------------------------------------------------------------------------------------------

I figured it out.

Since !DestBasePath! was containing the right value but %DestBasePath% was empty, I had to define a new variable within the same FOR command.

@echo off
setlocal enabledelayedexpansion

SET DisplayLines=40
MODE CON: COLS=150 LINES=!DisplayLines!


::SETTING STATIC VARIABLES
      SET CounterPath=0
      FOR /F "tokens=1-3 delims=:. " %%A in ('echo !time!') do set TheTime=%%A.%%B.%%C
      SET TheDate=!date!


::CREATING DATE VARIABLES
      For /f "Tokens=1-3 Delims=-" %%A in ('Echo !date!') do (set Year=%%A&& Set Month=%%B&& Set Day=%%C)


::READING INI FILES
      for /F "tokens=1,2 delims=^=" %%A in (Settings.ini) do SET Setting.ini_%%A=%%B
      for /F "tokens=1,2 delims=^>" %%A in (Paths.ini) do (
            SET /a CounterPath=!CounterPath! + 1
            SET SourceBasePath!CounterPath!=%%A
            SET DestBasePath!CounterPath!=%%B
      )


::SETUP HAS-BEEN FOLDER
      SET HasBeenFolder=!Setting.ini_HasBeenFolder!
      IF not exist !HasBeenFolder!  md !HasBeenFolder!
      IF not exist !HasBeenFolder!  ECHO.&&ECHO HAS-BEEN BASE FOLDER COULD NOT BE AUTOMATICALLY CREATED. PLEASE DO IT MANUALLY&&ECHO.&&PAUSE
      SET HasBeenFolder=!HasBeenFolder!\!Year!&&            IF not exist "!HasBeenFolder!" md "!HasBeenFolder!">NUL
      SET HasBeenFolder=!HasBeenFolder!\!Month!&&            IF not exist "!HasBeenFolder!" md "!HasBeenFolder!">NUL
      SET HasBeenFolder=!HasBeenFolder!\!Day!&&                  IF not exist "!HasBeenFolder!" md "!HasBeenFolder!">NUL
      SET HasBeenFolder=!HasBeenFolder!\!TheTime!&&      IF not exist "!HasBeenFolder!" md "!HasBeenFolder!">NUL


::MOVE HAS-BEENS (FILE DELETED FROM SOURCE OR ABOUT TO BE REPLACED.) TO HAS-BEEN FOLDER.
FOR /L %%A in (1,1,!CounterPath!) do (
            SET SourceBasePath=!SourceBasePath%%A!
            SET DestBasePath=!DestBasePath%%A!
            ::
            FOR /F "delims=" %%A in ('DIR /a-d /b /s !DestBasePath!') do (
                        ECHO --------------------------------
                        SET FileName=%%~nA%%~xA&& ECHO ** FileName=!FileName!
                        SET FilePath=%%~pA&&      ECHO ** FilePath=!FilePath!
                        ::SETUP DESTINATION FILE INFOS
                              SET DestFileFull=%%~fA&& ECHO ** DestFileFull=!DestFileFull!
                              SET DestFileSize=%%~zA&& ECHO ** DestFileSize=!DestFileSize!
                              SET DestFileDate=%%~tA&& ECHO ** DestFileDate=!DestFileDate!
                        ::SETUP SOURCE INFOS
                              FOR %%A in ("!DestFileFull!") do SET SourceFolder=%%~dA%%~pA
                              ECHO ** SourceFolder=!SourceFolder! === !DestBasePath!
                              SET DestBasePath1=!DestBasePath!
                              SET SourceFolder=!SourceFolder:%DestBasePath1%=!
                              SET SourceFileFull=!SourceFolder!!FileName!
                              ECHO ** SourceFolder=!SourceFolder!
                              IF EXIST !SourceFileFull! (
                                    FOR %%A in ("!SourceFileFull!") do SET SourceFileSize=%%~zA
                                    FOR %%A in ("!SourceFileFull!") do SET SourceFileDate=%%~tA
                                    ECHO ** SourceFileSize=!SourceFileSize!
                                    ECHO ** SourceFileDate=!SourceFileDate!
                                    IF !SourceFileDate! NEQ !DestFileDate! ECHO ** DATE IS NOT THE SAME
                              ) ELSE (
                                    ECHO ** FILE DOES NOT EXIST AT SOURCE
                              )
                  )
      )

PAUSE
exit
==> %DATE:~10,4%-%DATE:~4,2%-%DATE:~7,2%

This assumes that your date is in a format of aaa bb/cc/dddd

and will always extract as dddd-bb-cc

If your date were formatted at say just mm/dd/yyyy then this will not work.

I do have a routine that I use to account for various formats that can be set in Windows and this change the display of the %DATE% variable, I can include that small routine in my rewrite if you like?

~bp
Avatar of ReneGe

ASKER

Yes plz thanks
I only used that for me, I assumed you knew what your date format was, and I made mention that that code will only wok if your region is North America, if it is not you need to change the code to work with your output format.  you can find out your output format by typing:

ECHO "%DATE%" at the command prompt and looking at the output.

in North America the format will be:

"ddd MM/DD/YYYY"
(here is an example with today's date)
"Fri 08/13/2010"

Since I knwo this and I only work in NA, I just use the code:

%DATE:~4,2% to grab the current Month (Grabs character 4 to character 6)
%DATE:~7,2% to grab the current Day (Grabs character 7 to character 9)
%DATE:~10,4% to grab the current Year (Grabs character 10 to character 14)
( OR )%DATE:~-4% to grab the current year (Grabs THE LAST 4 characters)
I noticed you went back to this code:

 FOR /F "tokens=1-3 delims=:. " %%A in ('echo !time!') do set TheTime=%%A.%%B.%%C

Why bother echoing???  It only takes more timeup.  You can just parse the variable as a string.

This will work exactly the same, I use it in my code, more importantly it will give you a leading 0, your code will sometimes (between 12:00 AM and 9:59 AM) give you a leading space because it shows the time as " 0:00:00.00" to " 9:59:59:99" thereafter it will display the missing digit.  that is why you should use this instead:

FOR /F "Tokens=1-3 Delims=:." %%A ("%Time%") DO SET TheTime=%%A.%%B.%%C


Not only does this allow you to skip an unnecessary echo command, but it turns the leading space into a 0 which allows windows to sort the information properly, and ensures you don;t have an errant space in something.
 I notice you didn't really keep any of the improvements I pout in the other sections either...

  I know you said you were very concerned about the script taking a long time to execute so I tried to make as many statement be single-lined as possible.

  I tested all portions functionality except for the final looping which I haven't had time to do yet, you should consider the changes I made, because you should avoid using delayed expansion to save more time when it is unneeded.

  I suppose that is the crux of anything though, and i know I'm 'one to talk' because I like to be verbose.. lol.

Also, exit at the end of the file instead of nothing or GOTO :EOF is a poor choice because you can accidentally end up closing the command prompt you're running things in.
Avatar of ReneGe

ASKER

==>QCubed, Thanks for explaining. While at it, is there a code the will grab the last (let's say) 5 caracters?
Only of a variable.  that is why I do through pains in my code to put everythign in variable form.

Assuming you have a Variable named "VariableName"  and it's been set to the Value 1234567890

(as in SET "VariableName=1234567890")

Then you can do this to USE only the last 5 characters:

%VariableName:~-5%

Whatever you are doing with the variable it will resolve to this:  67890

AND you can use this to USE only the first five characters:

%VariableName:~0,5%

Whatever you are doing with the variable it will resolve to this: 12345

Also you can use this to USE only the characters from position 3 through position 7:
%VariableName:~3,5%

Whatever you are doing with the variable it will resolve to this: 45678
Avatar of ReneGe

ASKER

Thanks guys for your help and contribution.

I'll have more questions about this script but I'll create new threads so you can get more points.

Thanks again and cheers,
Rene
Sweet, thanks vMuch glad I could be of so much help, Bill is also a top-notch Expert.  Please remember to post links to the related questions on this question and back to this question on the other ones (just good practice)   =)
== QCubed

Thanks for the kind words, appreciated.

~bp
Okay, I'd suggest you take a look at this to see what you can learn, and of course, see if it works!  You'll probably notice other changes from your code, but here are a few notes:

Don't use !var! when you can use %var%.  Typically you only need to use the !var! delayed expansion when you are referencing a variable inside a code block where the variablt was set.  This is most commonly a FOR.

Don't use :: for comment lines, use REM.  :: is a kludge for comments, and when used inside a FOR loop can sometimes cause problems.  REM is the proper languages supported way for comments to be entered, and as such a future version of the command interpreter may remove the hole that allows :: to serve as comments.

In FOR /F loops there's no needs to ECHO a variable, just reference it in quotes.

I added my routine to get month, day and year independently of system date format.

The MD command will create all needed intermediate folders, no need to build them up manually one at a time, level by level.

I am really not a fan of multiple commands on a single line unless it adds to readability.  I prefer to slit these onto separate lines.  This is a somewhat personal preference, but take a look at how it looks each way.  Also, I find that the "simpler" that code looks when reading it, the easier it is to understand quickly, and the easier it is to maintain in the future, without breaking it!

I did some assorted cleanups and fixes in the main FOR loop getting the file names and dates, etc.  I resisted the urge to remove the extra variables being SET, since I suspect you are planning to build on this going forward.

Clearly you will note quite different styles and techniques between QCubed code and mine.  In some cases there may technical or software engineering reasons why one approach can be better than another, but in general a large amount of it is personal.  I always find it interesting to see how other people approach things in different ways than I do, and try and learn from it.  

Speaking of which, you'll notice I prefer quite a bit smaller indent levels than you gents.  With current editors typically language aware and often showing where blocks begin and end, or showing vertical guide lines.  As a result, I go with 2 or 3 spaces per indent level rather than the 6 or 8 some folks prefer.  Clearly this is a very personal preference and different people prefer different levels.  Withing a software project, or better still withing a company, I prefer things like this to be called out in a programming standards guide, so all code does things like indentation, naming conventions, capitalization the same.  But up here on EE where each problem is a small atomic solution, we all bring our personal preferences to the table.

Hope this helps.

~bp
@echo off
setlocal EnableDelayedExpansion
 
SET DisplayLines=40
MODE CON: COLS=150 LINES=%DisplayLines%
 
REM SETTING STATIC VARIABLES
SET CounterPath=0
FOR /F "tokens=1-3 delims=:. " %%A in ("%TIME%") do (
   set TheTime=%%A.%%B.%%C
)
 
REM Get month, day, and year (works on any date format)
call :GetDate "Month" "Day" "Year"
 
REM READING INI FILES
for /F "tokens=1,2 delims=^=" %%A in (Settings.ini) do (
   SET Setting.ini_%%A=%%B
   )
for /F "tokens=1,2 delims=^>" %%A in (Paths.ini) do (
   SET /a CounterPath=+1
   SET SourceBasePath!CounterPath!=%%A
   SET DestBasePath!CounterPath!=%%B
)
 
REM SETUP HAS-BEEN FOLDER
SET HasBeenFolder=!Setting.ini_HasBeenFolder!
IF not exist %HasBeenFolder% md %HasBeenFolder%
IF not exist %HasBeenFolder% (
   ECHO.
   ECHO HAS-BEEN BASE FOLDER COULD NOT BE AUTOMATICALLY CREATED. PLEASE DO IT MANUALLY
   ECHO.
   PAUSE
)
IF not exist "%HasBeenFolder%\%Year%\%Month%\%Day%\%TheTime%\" md "%HasBeenFolder%\%Year%\%Month%\%Day%\%TheTime%">NUL
 
REM MOVE HAS-BEENS (FILE DELETED FROM SOURCE OR ABOUT TO BE REPLACED.) TO HAS-BEEN FOLDER.
FOR /L %%A in (1,1,!CounterPath!) do (
   SET SourceBasePath=!SourceBasePath%%A!
   SET DestBasePath=!DestBasePath%%A!
   REM
   FOR /F "delims=" %%A in ('DIR /a-d /b /s !DestBasePath!') do (
      ECHO --------------------------------
      SET FileName=%%~nA%%~xA
      SET FilePath=%%~pA
      ECHO ** FileName=!FileName!
      ECHO ** FilePath=!FilePath!
      REM SETUP DESTINATION FILE INFOS
      SET DestFileFull=%%~fA
      SET DestFileSize=%%~zA
      SET DestFileDate=%%~tA
      ECHO ** DestFileFull=!DestFileFull!
      ECHO ** DestFileSize=!DestFileSize!
      ECHO ** DestFileDate=!DestFileDate!
      REM SETUP SOURCE INFOS
      CALL SET SourceFileFull=%%DestFileFull:!DestBasePath!=!SourceBasePath!%%
      ECHO ** SourceFileFull=!SourceFileFull!
      IF EXIST "!SourceFileFull!" (
         FOR %%B in ("!SourceFileFull!") do (
            SET SourceFileSize=%%~zB
            SET SourceFileDate=%%~tB
         )
         ECHO ** SourceFileSize=!SourceFileSize!
         ECHO ** SourceFileDate=!SourceFileDate!
         IF !SourceFileDate! NEQ !DestFileDate! ECHO ** DATE IS NOT THE SAME
      ) ELSE (
         ECHO ** FILE DOES NOT EXIST AT SOURCE
      )
   )
)
 
PAUSE
exit
 
REM Support subroutine to get date components
:GetDate [month-variable] [day-variable] [year-variable]
  REM Get date format settings from registry
  rem For REG.EXE 3.0 (Windows XP) and later versions
  for /F "tokens=3" %%A in ('reg query "HKCU\Control Panel\International" /v iDate 2^>NUL') do set "iDate=%%A"
  for /F "tokens=3" %%A in ('reg query "HKCU\Control Panel\International" /v sDate 2^>NUL') do set "sDate=%%A"
  rem For earlier REG.EXE versions
  rem for /F "tokens=3" %%A in ('reg query "HKCU\Control Panel\International\iDate" 2^>NUL') do set "iDate=%%A"
  rem for /F "tokens=3" %%A in ('reg query "HKCU\Control Panel\International\sDate" 2^>NUL') do set "sDate=%%A"
 
  REM Get the current system date (ignore day name if present)
  for %%A in (%Date%) do set "Today=%%A"
 
  REM Parse current date based on delimiter from registry, and assign to desired user variable
  for /F "tokens=1-3 delims=%sDate%" %%A in ("%Today%") do (
    if "%iDate%"=="0" set "%~2=%%B" & set "%~1=%%A" & set "%~3=%%C"
    if "%iDate%"=="1" set "%~2=%%A" & set "%~1=%%B" & set "%~3=%%C"
    if "%iDate%"=="2" set "%~2=%%C" & set "%~1=%%B" & set "%~3=%%A"
  )
  exit /b
)

Open in new window

Avatar of ReneGe

ASKER

Billprew this was very educative.

Could you please explain:
CALL SET SourceFileFull=%%DestFileFull:!DestBasePath!=!SourceBasePath!%%

Thanks,
Rene
I can explain.

As I mentioned in my Comment (08/12/10 08:48 PM, ID: 33426027) Above:

When you want to set a variable to show a portion of itself or replace a portion of itself as defined by another variable you actually need to CALL the Set command.  That functionality has nothing to do with Delayed expantion it's just how the command environment works.

The reason for this is because when you CALL set it takes the first variable and passes it as a parameter to the second variable, while when you do NOT call it doesn't understand that there IS a second variable to manipulate.

(Hence part of the reason I prefer CALLs to working with delayed expansion, but there is no reason you can't do both in a batch file, and it certainly can be very useful to use delayed expansion instead of calls at times or vice verse.)

Why this works this way:

Whenever you CALL a Command or other executable, the command environment you are in pauses, spawns a new command process, and passes any variables you specify to the new command process.

When you call a command and pass it a variable with another variable inside it it will evaluate the variable inside (assume you formatted correctly) before evaluating the variable on the outside.  where as if you DO NOT CALL you will evaluate the variable front forwards, so the best you could hope for via that method is to have a string of variables added together.

Was that clear for you?

~Q



 PS I have an updated version as well since Bill posted his I will do likewise.
Avatar of ReneGe

ASKER

Hey guys,

Thanks for all your help and teachings.

It was very educative.

Here is the link for my follow-up question:
https://www.experts-exchange.com/questions/26404456/Batch-File-Backup-Files-with-Has-Been-folder.html

Thanks again & cheers,
Rene