DOS Shell Script - Searching Strings

Hi,

I am writing a DOS batch program that, among other things needs to rename a file with a date stamp based on a format passed in part of an argument. i need to parse this format identifier from the argument (variable) to determine how to format the date stamp.

The variable  will come is as: "FileNameFormatOtherStuff.extension" an example would be: "filenameccyymmdd.pgp" where ccyymmdd would mean to create a variable to later be used to rename a file to something like: "FileName20120816.pgp" i can receive various formats the key being the occurrence of a specific group of characters like: ccyymmdd or yymm or yymmdd etc... there are about ten combinations possible. In some cases the string could have the identifier in the middle like this: "FileNameccyymmdddMoreStuff.csv".

I have no problem with parsing a date and building the correct filename, what i do need to determine is the following items: the length of the entire string, the starting position of the format identifier within the string the ending position of the format identifier and the position of the "." which is not always at the end of the format identifier.

I have been trying to use the FOR/f command and am failing miserably.....HELP!

Thanks! -  Jennifer
jennifer_EDI_GalAsked:
Who is Participating?
 
Steve KnightConnect With a Mentor IT ConsultancyCommented:
Try this.... you can see a potential issue though perhaps and why I suggesting replacing more than one string, i.e. yymm.  I have added further lines in there to look for just dd and replace with !dd! but in this case it then found "TestDddmmyy" and replaced the first two Dd with the day..


Steve

Today is 20 12 08 17
The new name for Test Ayymmdd.doc is Test A120817.doc
The new name for Test Bccyymmdd.doc is Test B20120817.doc
The new name for Test Cmmdd.doc is Test C0817.doc
The new name for Test Dyymm.doc is Test D1208.doc
The new name for Test Dddmmyy.doc is Test 17d0812.doc
Press any key to continue . . .

@echo off
setlocal enabledelayedexpansion
echo wscript.echo left(year(date),2) ^& "," ^& right(year(date),2) ^& "," ^& right(100 + month(date),2) ^& "," ^& right(100+day

(date),2)  > "%temp%\dateparts.vbs"
for /f "tokens=1-4 delims=," %%a in ('cscript //nologo "%temp%\dateparts.vbs"') do (set cc=%%a)&(set yy=%%b)&(set mm=%%c)&(set dd=%

%d)

echo Today is %cc% %yy% %mm% %dd%

call :Test "Test Ayymmdd.doc"
call :Test "Test Bccyymmdd.doc"
call :Test "Test Cmmdd.doc"
call :Test "Test Dyymm.doc"
call :Test "Test Dddmmyy.doc"

pause

exit /b

:Test
set myfilename=%~1
set myfilename=%myfilename:ccyymmdd=!cc!!yy!!mm!!dd!%
set myfilename=%myfilename:yymmdd=!yy!!mm!!dd!%
set myfilename=%myfilename:yymm=!yy!!mm!%
set myfilename=%myfilename:mmdd=!mm!!dd!%
set myfilename=%myfilename:mm=!mm!%
set myfilename=%myfilename:dd=!dd!%
set myfilename=%myfilename:yy=!yy!%
set myfilename=%myfilename:cc=!cc!%
echo The new name for %~1 is %myfilename%

exit /b

Open in new window

0
 
Steve KnightIT ConsultancyCommented:
Hmm, would probably be much easier doing this in a few lines of VBS than batch though all is possible one way or another.

Using for loop you can split the filename at the . using %%~xA and %%~nA to get name and extension but to find the date bit in the middle.  How do you determine between

MyBikeIs1500cc-YY-MM-DD.doc

being CC or century... etc.

i.e. is there a rule for how to find the dd/mm/yy bits etc - is this human entered or from a different system?

if it is always certain formats then you could first test for ccyymmdd then yymmdd etc.

You can do a search and replace, e.g.

set myfilename=%myfilename:ccyymmdd=20120502%
set myfilename=%myfilename:yymmdd=120502%
set myfilename=%myfilename:yymm=1205%
set myfilename=%myfilename:mmdd=0502%

etc.

Would suggest getting the date using VBS (or WMIC) methods which is why I wondered if the whole lot in VBS might be better plan?
I use this for dates: http://www.experts-exchange.com/Programming/Languages/Visual_Basic/VB_Script/Q_27823783.html 

Steve



Steve
0
 
jennifer_EDI_GalAuthor Commented:
Steve,

Thanks for the input. there is a list of about 700 file names that need to be routed to several different applications, including database parsing of the content, archiving, cryptographic operations etc.... i do not have the luxury of a real development environment only SQL server, which could more readily parse a variable from a stored procedure but i am not sure about passing the results back to the calling DOS shell, it may be more bother then going this route.

I am literally getting the characters "ccyymmdd" etc... in the file name. getting the date is not an issue, i already have parsed it into variables i call %mm%, %dd% etc... i just need to know which format to arrange them into based on the content of this string, which btw is generated by some legacy application we have no control over.

the search and replace may be a viable answer. I can certainly replace someting like "yy" with %yy%.

this operation is the final step before they get FTP'd to 700 different trading partners out there in the ozone. it is these partners who define what the date stamp needs to look like so they can automagically parse them on their side of the equation.

could you please show me an example of how to substitute a variable like that? Say replace the literal "yy" with the content of my %yy% variable within a string, lets call it %output_file%?

Thanks again,
Jen
0
The Lifecycle Approach to Managing Security Policy

Managing application connectivity and security policies can be achieved more effectively when following a framework that automates repeatable processes and ensures that the right activities are performed in the right order.

 
Steve KnightIT ConsultancyCommented:
BTW the key bit here is the "setlocal enabledelayedexpansion"

that means that the using !variable! is not evaluated until the code runs that line... so in this case it evaluates the !cc! to the right century then uses that in the rest of the line.

Otherwise if we just used %filename:cc=%cc%% it just doesn't work properly...

Today is 20 12 08 17
The new name for Test Ayymmdd.doc is Test A.do%y%m%d%y%m%d%y%m%m%d%m%d%y%c%
The new name for Test Bccyymmdd.doc is Test B.do%y%m%d%y%m%d%y%m%m%d%m%d%y%c%
The new name for Test Cmmdd.doc is Test C.do%y%m%d%y%m%d%y%m%m%d%m%d%y%c%
The new name for Test Dyymm.doc is Test D.do%y%m%d%y%m%d%y%m%m%d%m%d%y%c%
The new name for Test Dddmmyy.doc is Test d.do%y%m%d%y%m%d%y%m%m%d%m%d%y%c%
0
 
QlemoBatchelor, Developer and EE Topic AdvisorCommented:
Steve,

I've verified the case insensitive string replace issue - strange, I never was aware of that!

However, I think you got the subject wrong. The format template is coming in as a separate value, and the result needs to be applied to a bunch of file names. The file names do not contain the formatting stuff.
That does not change much, as the only additional step to take would be to set up another replacement operation for (e.g.) !filename!. If we do that as last replacement step, no potential conflicts of template characters in the file name can occur.
0
 
Steve KnightIT ConsultancyCommented:
Hmm, might be right there Qlemo but not how I read it?  Will see what comes back and one of us can soon shift things around if needed.

Steve
0
 
QlemoBatchelor, Developer and EE Topic AdvisorCommented:
If I'm correct, then applying my thoughts to the code given results in (I've removed the code retrieving the date parts, as that is done already somewhere else according to the OP):
@echo off
setlocal enabledelayedexpansion

call :Test "Test Ayymmdd.doc"
call :Test "Test Bccyymmdd.doc"
call :Test "Test Cmmdd.doc"
call :Test "Test Dyymm.doc"
call :Test "Test Dddmmyy.doc"

pause

exit /b

:Test
set myfilename=%~1
set mask=%~2
set mask=%mask:ccyymmdd=!cc!!yy!!mm!!dd!%
set mask=%mask:yymmdd=!yy!!mm!!dd!%
set mask=%mask:yymm=!yy!!mm!%
set mask=%mask:mmdd=!mm!!dd!%
set mask=%mask:mm=!mm!%
set mask=%mask:dd=!dd!%
set mask=%mask:yy=!yy!%
set mask=%mask:cc=!cc!%
set myfilename=%mask:filename=!myfilename!%
echo The new name for %~1 with format %~2 is %myfilename%
exit /b

Open in new window

0
 
jennifer_EDI_GalAuthor Commented:
Thanks!,
Actually you are right the format will be comming in as part of the filename, not as a seperate value passed in a parameter. it is a little less elegant than i thought it could be, but it really does not matter because there are only a finite set of combinations possible. if i get too "granular" (i hate buzzwords) then stuff like "CCsPizzaCCYYMM.pgp" could be a problem :P so i will look for the entire date structure.

Thanks again for all your help,
Jen
0
 
QlemoBatchelor, Developer and EE Topic AdvisorCommented:
"CCsPizzaCCYYMM.pgp" is a problem. Both CCYYMM and CC are found and replaced ... You will most likely have to remove
set myfilename=%myfilename:mm=!mm!%
set myfilename=%myfilename:dd=!dd!%
set myfilename=%myfilename:yy=!yy!%
set myfilename=%myfilename:cc=!cc!%

Open in new window

as that is too ambigious.
0
 
jennifer_EDI_GalAuthor Commented:
You are correct,

Yes I couls see that, hence teh CC's Pizza example, i think MMCandy would be an issue too :D I will only be searching for complete valid formats, not just the characters 'cc' or 'yy' etc....

Thanks once again,
Jen
0
 
jennifer_EDI_GalAuthor Commented:
BTW - Here is the final little piece of code (there were only five variations in the current list) the variables %mm%, %dd% and etc... were set in an init vars section :

REM ::==================================================================
REM :: RENAME FILE IF NECESSARY
REM ::==================================================================

:RENAME

IF %INPUT_FILE%==%OUTPUT_FILE% GOTO :NO_RENAME

setlocal enabledelayedexpansion

SET OUTPUT_FILE=%OUTPUT_FILE:ccyymmdd=!cc!!yy!!mm!!dd!%
SET OUTPUT_FILE=%OUTPUT_FILE:ccyymm=!cc!!yy!!mm!%
SET OUTPUT_FILE=%OUTPUT_FILE:yymmdd=!yy!!mm!!dd!%
SET OUTPUT_FILE=%OUTPUT_FILE:yymm=!yy!!mm!%
SET OUTPUT_FILE=%OUTPUT_FILE:mmdd=!mm!!dd!%

:NO_RENAME

IF %DO_WE_ENCRYPT%==%YES% GOTO :CRYPTO_STUFF

REM ::==================================================================
for grins (and for any other poor person who ever needs to do this)  here is how i set up the date time stuff:

REM ::==================================================================
REM ::= setup date and time variables so we can time stamp stuff                                    =
REM ::==================================================================

REM :: set date_string = system date
for /f "tokens=1-5 delims=/ " %%d in ("%date%") do set date_string=%%g%%e%%f
if not %errorlevel%==0 goto :ERROR_1

REM :: set time_string  
for /f "tokens=1-5 delims=:" %%d in ("%time%") do set time_string=%%d-%%e
if not %errorlevel%==0 goto :ERROR_1


REM :: Parse Date And Time into Variables to use when renaming files

set cc=%date_string:~0,2%
set yy=%date_string:~2,2%
set mm=%date_string:~4,2%
set dd=%date_string:~6,2%
set my_month=%date_string:~4,2%
set hh=%time_string:~0,2%
set mn=%time_string:~3,2%
if not %errorlevel%==0 goto :ERROR_1

REM :: echo %cc% %yy% %mm% %dd% %hh% %mn%
0
 
Steve KnightIT ConsultancyCommented:
I'm sure you are aware of them but the issues with getting date / time by using %date% and %time%, if you, for instance run the batch on a different pc, os, user, scheduled it etc. then you could have a dozen different date formats, leading zeroes, different order, day name at the front, or not etc.

Anyway that's why I use VBscript, or WMIC methods hence my article I quoted... hmm or actually looks like I posted link to an earlier Q by mistake before, sorry.

http://www.experts-exchange.com/OS/Microsoft_Operating_Systems/MS_DOS/A_1153-Using-dates-in-batch-files-scripts.html

Steve
0
 
jennifer_EDI_GalAuthor Commented:
Thanks Steve,

Fortunately I own the server, which is brand spanking new, that this will be running on and can control how the date is formatted. One of the few things that i can control in this environment. So it should not be a concern for the next couple of years.

Hummmm come to think of it I remember writing code in the early eighties saying that this thing will have issues in the year 2000 but heck it will not be around then, I actually got paid to fix it 15 years later:)

In this case it is only temporary, scheduled to be replaced by real middleware within the next couple of years so it should be fine as the stop gap solution it is intended to be.

Jen
0
 
Steve KnightIT ConsultancyCommented:
Ok, well ask if you need any other help here otherwise look forward to getting a "good answer"!
0
 
jennifer_EDI_GalAuthor Commented:
BTW Guys, this is my first experience with "Experts Exchange". I am blown away by the rapid responses I have received and the thoughtful solutions suggested. Kudos to all of you for taking your time to help those with questions like mine.
0
 
Steve KnightIT ConsultancyCommented:
No problem and glad it has been useful - have learned a lot here myself over the years.

You will find "Accept as answer" and "accept multiple answer" buttons / links there somewhere (I don;t use that side much!)

Steve
0
 
jennifer_EDI_GalAuthor Commented:
Thanks Again, Jen
0
 
jennifer_EDI_GalAuthor Commented:
Thanks!
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.