![]()
[<<]Message[>>] [<<]Author [<<]Subject[>>] [<<]Thread[>>]
Number : 10658 Date : 2005-02-28 Author : jeffneely2003 Subject : Re: Flatten Subdirectories? Size(KB) : 6
--- In xxcopy@yahoogroups.com, "Garry Deane" wrote: > > --- In xxcopy@yahoogroups.com, "jeffneely2003" wrote: > > Wow! Thanks a lot John. That was a very informative > > introduction to Windows scripting for me. In fact, I had > > to understand how it worked before I even tried running it > > -- so I spent a few hours reading and testing some of those > > commands that I'd never seen used before. I had no idea > > batch scripting on Windows could do this. > > > > Do you have any online scripting references you'd recommend? > > > > I found these: > > http://labmice.techtarget.com/articles/batchcmds.htm > > http://www.ss64.com/nt/index.html > > > > But I still never found anything that explained the usage of > > ! as in: > > set Y=!P:%SRC%=! > > (assuming it is "evaluate", similar to using %) > > > > Or what this does: > > setlocal enabledelayedexpansion > > To add to what John has already said, SETLOCAL localises > environment variables so that they only exist within the > section of batch code between a SETLOCAL...ENDLOCAL pair. > After an ENDLOCAL keyword is reached, variables that have > been newly defined after the SETLOCAL are discarded and > previously defined variables are restored with their > values from before the SETLOCAL. Try this bit of code to > see localisation in action. Note that there is an implied > endlocal when the end of the batch file is reached. If > you use SETLOCAL within the batch file, all variables > defined after that point will be discarded when the batch > file terminates. > > @echo off > set var1=one > setlocal > set var1=one+one > set var2=two > echo [%var1%] [%var2%] > endlocal > echo [%var1%] [%var2%] > > The ENABLEDELAYEDEXPANSION keyword allows variable expansion > to be delayed until the variable is actually used. Delayed > expansion variables are signified using surrounding ! instead > of % e.g. !var1! rather than %var1%. Normally, when Cmd.exe > reads a line of batch code and interprets what to do, the > value of environment variables are substituted into the line > very early in the parsing process. Any strings surrounded with > % signs are replaced with the actual value of the matching > environment variable name. > > This process of variable substitution becomes important when > using multiple commands on one line such as when using "&" or > (...) to create compound command lines. If you have a multi > command statement such as the following: > > @echo off > set var1=one > ( > set var1=one+one > set var2=two > echo [%var1%] [%var2%] > ) > echo [%var1%] [%var2%] > > then everything between the parentheses are treated as one > line. Cmd reads the entire (....) sequence up to the closing > parenthesis then immediately substitutes the %var1% and %var2% > pieces with the actual values of these variables. This happens > BEFORE the "set var1=one+one" and "set var2=two" lines are > executed so the values that are substituted are the values > that existed before the first "(" is encountered i.e. > var1=one and var2=nul. > > This behaviour can be modified with the ENABLEDELAYEDEXPANSION > keyword so that the substitution doesn't occur until the > command containing the !var! is actually executed. Change > the above code to the following and you'll see the difference. > > @echo off > set var1=one > ( > set var1=one+one > set var2=two > echo [!var1!] [!var2!] > ) > > This is the most command use of delayed expansion. In John's > code however, he used a mix of ! and % to control the ORDER > in which the variables were substituted. His line was similar > to the following: > > set P=abcd\defg > set SRC=abcd > set Y=!P:%SRC%=! > > This gets substituted in the following way: > > 1. Replace all %....% with the matching variable name > set Y=!P:%SRC%=! -> set Y=!P:abcd=! > > 2. Replace all !....! with the matching variable name > set Y=!P:abcd=! -> set Y=!abcd\defg:abcd=! -> set Y=\defg > > > A few follow-on questions came up while I was trying to > > convert this into a full-fledged utility: > > > > 1) How would I properly parameterize this so that the SRC > > and DST could be passed in. And if the DST isn't passed, to > > use a default dir that is the SRC + \output? > > Batch parameters are accessed using %1, %2, %3 etc. to refer > to the 1st through 3rd parameters (up to a max of 9). If you > want to pass the src and dst as parameters, you would execute > your batch command like this: > > batch.bat "c:\Program Files\" d:\backup > > Within the batch file you'd do something like this: > > @echo off > setlocal enabledelayedexpansion > set src=%~1 > if not defined src set src=c:\Program Files\ > set dst=%~2 > if not defined dst set dst=d:\backup\ > > Another way to do the same thing might be: > > @echo off > setlocal enabledelayedexpansion > set src=c:\Program Files\ > if not "%~1" == "" set src=%~1 > set dst=d:\backup\ > if not "%~2" == "" set dst=%~2 > > Note the use of the ~ in %~1. This strips out any quotes > that may be used with paths that contain spaces and gives > you the variable in a "known" unquoted state. You can then > add your own qoutes as needed within subsequent commands. > > > 2) How would I allow an optional parameter to be passed in > > for the separator char, and use a default value if none is > > passed? > > > > eg FLATTEN SRC [DST] [/Sc] > > where c is the separator char to use when flattening the dirs > > This gets a bit trickier. Generally you'd do similar to > the above for the paths and require that if a separator > is used, it MUST be the 3rd parameter i.e. the [DST] parameter > must be given even if it's the default value. If you want > to allow both or all parameters to be optional, you need > to examine the contents of the parameters to see whether > any start with /S or /s. Possibly something like this > (assumes that /S if given is the last parameter): > > @echo off > setlocal enabledelayedexpansion > set src=c:\Program Files\ > set dst=d:\backup\ > set sep= > > if "%~1" == "" goto :next > set param=%~1 > if /i "%param:~0,2%" == "/s" ( > set sep=%~1&goto :next) else set src=%~1 > if "%~2" == "" goto :next > set param=%~2 > if /i "%param:~0,2%" == "/s" ( > set sep=%~2&goto :next) else set dst=%~2 > if not "%~3" == "" set sep=%~3 > :next > echo [%src%] [%dst%] [%sep%] > > > 3) How would I create the DST dir if it doesn't exist? > > As John has already explained, there's no need to do this > as xxcopy will create it automatically if it doesn't exist. > > Garry Garry, thank you so much for further explaining the delayedexpansion setting. I tried some of the examples you posted to make sure I understood the way it works. It took a few runs for it to sink in, but I think I understand now. Thanks again for the detailed explanation -- I really do appreciate the time you spent (and the time John spent) posting answers to my questions. I've got a script now that does exactly what I wanted it to do. -Jeff
This message if part of XXCOPY's message Archive. The archive contains all the messages posted at Yahoo!Groups: XXCOPY.