Help - Search - Members - Calendar
Full Version: BAT Script Help
Hydrogenaudio Forums > Misc. > Off-Topic
SamHain86
I have basically taught myself the basics of writing BAT scripts after learning to write my own commands in REACT2.

I have a script that is designed to go through a set of MP3 folders, tag replaygain values, and then do file hashes of the files. My code looks like this:
CODE
@ECHO OFF
SET dest="G:\EXPERIMENT\Classical\Classical Masterpieces of the Millennium"
SET gaintool="C:\program files\react2\tools\metamp3.exe"
SET gaintoolopt=--replay-gain
SET hashtool="C:\Program Files\ReHash\rehash.exe"
SET hashtoolopt=-none -crc32 -md5 -sha1 -tiger
SET files=*.mp3
PUSHD %dest%
FOR /D %%f IN (*) DO (PUSHD %%f && TITLE GAIN ANALYSIS %%f && %gaintool% %gaintoolopt% %files% && TITLE HASH ANALYSIS %%f && %hashtool% %hashtoolopt% %files% >> "%%f.hash.txt" && POPD)


The script works fine on it's own, but I want to add more commands and get a better understanding of how BATs work. I have been told I can pass variables between one BAT and another, but every reference I find doesn't give an example! All I need to see is a really simple example of one BAT calling another, and the called BAT using variables of the first. The second one echoing variables from the first and it's own variables would be fine.

Any suggestions?

QUOTE(Update 1)
I rewrote the code using Greynol's suggestion as it makes my life that much easier. Synthetic Soul, thanks again for showing how to pass variables from one BAT to another, however I did not imagine that the variables I passed would somehow retain their original names.

CODE
@ECHO OFF
SET dest=G:\MEDIA\CDDA_ARCHIVE\Classical

SET gaintool="C:\program files\react2\tools\metamp3.exe"
SET gaintoolopt=--replay-gain
SET hashtool="C:\Program Files\ReHash\rehash.exe"
SET hashtoolopt=-none -crc32 -md5 -sha1 -tiger
SET files=*.mp3

PUSHD "%dest%"
FOR /D %%f IN (*) DO (
TITLE %%f
ECHO %%f
PUSHD "%dest%\%%f\Classical Masterpieces of the Millennium (1999)\"

TITLE %%f Gain Analysis
ECHO ----- Gain Analysis
%gaintool% %gaintoolopt% %files%

TITLE %%f Hash Analysis
ECHO ----- Hash Analysis
%hashtool% %hashtoolopt% %files% >> "%%f.hash.txt"

ECHO ----- %%f processing complete
POPD
)


Also, as Synthetic Soul pointed out, Windows does seem to use the modify date. I ran a program that changes such values, and my BAT works alphabetically now.
Synthetic Soul
This isn't something that I have done a lot, but I have tested the possibilities a couple of times. I would take a look at the call function, on this very useful site.

As a very simple example here is the code for two batch files, one.bat and two.bat. If both are in the same folder running one.bat will result in "Hello World!" and "Goodnight America" being echoed to the console:

one.bat
CODE
@ECHO OFF
SET x=Hello World!
CALL two.bat "%x%"
PAUSE

two.bat
CODE
SET x=Goodnight America!
ECHO %~1
ECHO %x%

NB: Notice the use of %~1 (as opposed to %1) to remove quotes from a parameter. Check the page on parameters for some useful (invaluable) tips.

You may have noticed, if you have used any of my REACT config code, or seen any of my other batch files, that I tend to use CALL to create what I think of as functions (described as subroutines in the page referred to above).

For example, I would rewrite your batch file as so:

CODE
@ECHO OFF
SET dest="G:\EXPERIMENT\Classical\Classical Masterpieces of the Millennium"
SET gaintool="C:\program files\react2\tools\metamp3.exe"
SET gaintoolopt=--replay-gain
SET hashtool="C:\Program Files\ReHash\rehash.exe"
SET hashtoolopt=-none -crc32 -md5 -sha1 -tiger
SET files=*.mp3

PUSHD %dest%
FOR /D %%f IN (*) DO CALL :GainAndHash "%%f"

GOTO :EOF

:GainAndHash
PUSHD %1
TITLE GAIN ANALYSIS %1
%gaintool% %gaintoolopt% %files%
TITLE HASH ANALYSIS %1
%hashtool% %hashtoolopt% %files% >> "%~1.hash.txt"
POPD
GOTO :EOF

By using:

CODE
CALL :GainAndHash "%%f"

... rather than just:

CODE
GOTO GainAndHash

... you can pass as many parameters to the subroutine as you want, referred to numerically - this first being %1, the second %2, etc. GOTO :EOF is used to return from the subroutine, and also at the end of the main part of the script to exit, and skip any subroutine code that follows.

You should probably be aware of SETLOCAL and ENDLOCAL, which are mentioned in the page also. I must admit that I tend to just hack my scripts together and don't worry about them. Perhaps you may want to consider using them though.

Edit: Amended example batch files to fit the requirements.
SamHain86
All right! Thanks Synth. One question, why would my FOR commands not be running in numerical order? All the files are numbered by track and it just seems to randomly pick 'em.
Synthetic Soul
I've no idea to be honest.

I noticed this myself on my XP laptop. A script that iterated through files in alphabetical order on my Win 2K PC stopped doing so when ran on the laptop. It appeared to me (I didn't examine too closely) that they were being processed in modified date order, rather than in order of filename.

I can't vouch for this, or suggest how to change to the attribute used for sorting. I'd be interested to hear of any testing that you may do, or from someone in the know though.

If it is absolutely necessary to run in filename order - and you can't find how to change the order of FOR - you may be able to use DIR to create a list of files (DIR /B /O:N) and then process that list using FOR.

SamHain86
I suspected it was using the modify date. What is stranger is that the program Rehash can do bulk processing of files when you specify a wildcard. What doesn't make sense is that when I move it out of the FOR iteration and let it perform the bulk on its own, it hashes the files in a different order. I'll do one then the other to see what is going on, but at a later date.

I hate it when the things I am interested are interrupted by actual work. school, eating, friends, sleep, etc. /laughs/ I'm not really that introverted... am I?
greynol
QUOTE(SamHain86 @ Jan 27 2008, 15:32) *
I hate it when the things I am interested are interrupted by actual work. school, eating, friends, sleep, etc. /laughs/ I'm not really that introverted... am I?
Dunno. Do you define yourself (possibly unknowingly) through your interactions with others? I believe this is the original definition of extrovert as opposed to the common street definition of simply meaning outgoing/boisterous.

Anywho, you can test the differences using the ECHO command, though I really don't know why the file order is behaving differently through different methods.

I'm not sure if you are using && to make sure the previous command works correctly, but I would normally structure my FOR statements this way:

CODE
FOR /D %%f IN (*) DO (
  PUSHD %%f
  TITLE GAIN ANALYSIS %%f
  %gaintool% %gaintoolopt% %files%
  TITLE HASH ANALYSIS %%f
  %hashtool% %hashtoolopt% %files% >> "%%f.hash.txt"
  POPD
)

This is just a general comment and is not intended to detract from the excellent advice Synthetic Soul has given.
SamHain86
Greynol that is a fantastic solution... one I didn't even consider.

Thank you all!
smok3
can't add anything to this suggestions, you can however find some of my ugly *.bat hacks here:
http://somestuff.org/bat/
SamHain86
In order to practice what I preach, some updates. I went with Greynol's method. I hadn't even considered that I would just bracket code into the FOR loop.

Also, windows does seem to indeed process files through the command line based on the modify date. I used a program to set these dates all to the same time, and then it functions numerically first, then alphabetically, and so on.
Synthetic Soul
In most circumstances using brackets is fine.

One side effect I don't like is the localisation of variables - which stops you from amending them within brackets.

I have created two examples, and also post their results:

Code
CODE
@ECHO OFF
SET /A x=1
FOR /L %%G IN (1,1,10) DO (
    SET /A x=%x%+1
    ECHO %x%
)
ECHO %x%
PAUSE

Result
CODE
1
1
1
1
1
1
1
1
1
1
2
Press any key to continue . . .

Code
CODE
@ECHO OFF
SET /A x=1
FOR /L %%G IN (1,1,10) DO CALL :Inc
ECHO %x%
PAUSE
GOTO :EOF

:Inc
SET /A x=%x%+1
ECHO %x%
GOTO :EOF

Result
CODE
2
3
4
5
6
7
8
9
10
11
11
Press any key to continue . . .

I'm not warning you away from using brackets, but am just pointing out an issue that took me a while to realise, so will hopefully help you avoid it. Use brackets where you are most comfortable, but if you need to update a variable (or more) within the loop you may need to look to other methods.
greynol
Brackets are also useful for IF statements. wink.gif
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Invision Power Board © 2001-2008 Invision Power Services, Inc.