omg
omg

Reputation: 139862

What does this batch file code do?

What does this bat code do?

for /f %%i in ('dir /b Client\Javascript\*_min.js') do (
    set n=%%~ni
    set t=!n:~0,-4!
    cp Client\Javascript\%%i build\Client\Javascript\!t!.js
)

What does %%~ni,~n:~0,-4!,%%i,!t! mean?

Upvotes: 0

Views: 708

Answers (4)

moonshadow
moonshadow

Reputation: 89065

%~ni expands to just the filename part of i.

!n:~0,-4! expands to all but the last four characters of n.

In general, help for at the command prompt will give an overview of the multitude of ways for can expand variables these days.

Upvotes: 1

Joey
Joey

Reputation: 354516

for /f %%i in ('dir /b Client\Javascript\*_min.js') do (

Iterate over every file in the Client\Javascript folder that match "*_min.js". Thedircommand andfor /f` are totally unneeded here, though and only complicate things, especially when file names contain spaces, commas and the like. A more robust and simpler alternative would be

for %%i in (Client\Javascript\*_min.js) do (

But that's just beside the point. People tend to write unelegant batch files sometimes, ignoring the pitfalls and common errors. That's just one example of that.

        set n=%%~ni

Creates a variable n, containing the file name (without any directory information or extension) of the file currently processed. We remember that the for statement iterates over every file it finds. With this line starts what it does with those files.

        set t=!n:~0,-4!

Creates a second variable, t, containing everything but the last four characters of the file name. This essentially strips away the "_min"

        cp Client\Javascript\%%i build\Client\Javascript\!t!.js

Finally, this copies the original file to the directory build\Client\Javascript with the new name, just constructed. So a file like Client\Javascript\foo_min.js will be copied to Client\Javascript\foo.js. The !t! here is just a delayed-evaluated environment variable. More on that below. Here it should suffice that it just inserts the contents of said variable at that point in the line.

Again, bad practice here that will break in numerous interesting ways:

  1. cp is not a command on Windows so this batch will assume cygwin, GNUWin32 or similar things installed. I tend to avoid having too many unneeded dependencies and stick to what Windows provides; in this case the copy command. Two bytes won't kill anyone here, I think.
  2. No quotes are around either argument. Leads to interesting results when spaces start appearing in the file name. Not good, either.

As for why delayed expansion was used (! instead of % surrounding the variables: The for command consists of everything in the block delimited by parentheses here as well. The entire block is parsed at once and normal variable expansion takes place when a line/command is parsed. That would mean that every variable in the block would be evaluated before the loop even runs, leaving just the following:

for /f %%i in ('dir /b Client\Javascript\*_min.js') do (
        set n=%%~ni
        set t=
        cp Client\Javascript\%%i build\Client\Javascript\.js
)

which is certainly not what you want in this case.

Delayed expansion is always needed when creating and using variables in a loop such as this. A workaround not needing delayed expansion would be to offload the loop interior into a subroutine:

for /f %%i in ('dir /b Client\Javascript\*_min.js') do call :process "%%i"
goto :eof
:process
set n=%~n1
set t=%n:0,-4%
copy "Client\Javascript\%~1" "build\Client\Javascript\%t%.js"
goto :eof

Since the subroutine is not a single "block" (something delimited by parentheses) it will be parsed line by line as usual. Therefore it's safe to use normal expansion instead of delayed expansion here.

Upvotes: 2

Mac
Mac

Reputation: 8339

A complete help for the FOR command can be found on the Microsoft TechNet site. See here for more information on delayed expansion :

// Pseudo code
for each file named *_min.js in the specified directory
    n is set to the file name (*_min)
    t is set to the file name, excluding the last 4 characters (*)
    the file is copied and renamed t.js to the specified directory

Upvotes: 1

Michael Madsen
Michael Madsen

Reputation: 55009

Keep in mind that in batch files, you need to escape percentage signs unless you're referring to arguments given to the batch file. Once you remove those, you get

for /f %i in ('dir /b Client\Javascript\*_min.js') do (
        set n=%~ni
        set t=!n:~0,-4!
        cp Client\Javascript\%i build\Client\Javascript\!t!.js
)

%i is the declaration of a variable used to place the current file for has found. %~ni extracts the filename portion of %i. !n:~0,-4! uses delayed expansion to remove the last four characters from %n% (set in the previous line) !t! is simply delayed expansion of the %t% variable set in the previous line.

Delayed expansion is used because otherwise, the variables will be substituted as soon as the line is encountered, and future iterations will not re-expand the variable.

Upvotes: 2

Related Questions