Showing posts with label NT. Show all posts
Showing posts with label NT. Show all posts

Friday, 13 April 2012

Batch programming: defaulting user input

This is a really simple script which sets a variable to a default value if the user doesn't provide input when asked.

set /P val=Please enter value: || set val=default


If the user enters a value, the %val% variable is set to the given value. Otherwise (if the user simply pressed Enter) 'default' is used instead.

Neat :).

Thoughts?

Friday, 22 August 2008

Batch programming tip #17: Moving/Copying hidden/system folders and files

A recent question about renaming a folder (on computing.net) brought to my attention the fact that move (which I usually use to rename folders) and also rename won't work on hidden/system files.

To avoid this 'issue' you must change the folder's system attributes.
First we define our original and destination folders.

set oldp=[define original folder here]
set newp=[define destination folder here]

Then we set the h (hidden) and s (system) attributes off (-h -s), move the folder, and switch the attributes back on again (+h +s).

attrib -h -s %oldp%
move %oldp% %newp%
attrib +h +s %newp%

You can also change all the file attributes within the folder, by using the /S modifier. And all (sub-)directories by using /D.

For instance:

attrib -h -s %oldp% /S /D


Will switch off the hidden and system attributes for (sub)folders and files in the %oldp% folder.

The same sort of thing happens with xcopy.
If you want to use xcopy on hidden/system files you must add the correct modifiers like so:

set oldp=[define original path here]
set newp=[define destination here]
xcopy %oldp% %newp% /H /S

Or only "visible" files will get copied.

I would love any additional input you may have about this.

Thoughts?

Saturday, 16 August 2008

Batch programming tip #16 (part 2): getting property values from an ini file

This is just a slight variation on the previous post on working with *.ini files.
Here we only retrieve property values but not sections or property names.

@echo off
setlocal enabledelayedexpansion

:init_vars
set ini_file=my.ini
goto show_values

:show_values
for /F "tokens=1,2 delims==" %%L in (%ini_file%) do (
if not [%%M]==[] (
echo Value: %%M
)
)
goto eof

:eof
echo Press any key to quit
pause > NUL


Simple :-).

Thoughts?

Monday, 11 August 2008

Batch programming tip #16: Reading a property from an INI file

You are going to start thinking batch an I are having a love-hate relationship but there was an interesting question on computing.net recently. Someone asked how to get a property from an INI file and/or print things to an ini file or text file.

This was my effort at it.

File: - my.ini -

[provider]
name=ETH
organization=Stardust

[file]
server=192.168.254.42 ; use IP address
port=8080
file=wonderful.txt


The aim of the following batch is to retrieve the server IP address.
To do this we read all the lines of the ini file (that is each first "token" of every line, but because the property=value entities don't contain any default delimiters the first token will actually be the property=value pair on each line).

Then we try matching the beginning of the line with our property name.
If it matches, bingo, get the remaining string value and output it to ini/txt.

File: - ini_bat.bat -

@echo off
setlocal enabledelayedexpansion

:init_vars
:: this is our ini file path
set ini_file=my.ini
:: this is the key for which we want to retrieve a value
set key=server
:: this is the length of our key word (e.g. 'server')
set keylen=6
:: this is the index at which the equal sign should be
set /a eqsign=%keylen%+1
:: tmp dir name (should be empty)
set tmp_dir=tmp000
:: make temp dir
if not exist %tmp_dir% mkdir %tmp_dir%
goto get_key

:get_key
set tmp_file=%tmp_dir%\tmp.txt
:: this read the first token of every line, shouldn't be spaces in the ini file properties
for /F %%L in (%ini_file%) do (
set line=%%L
set linestart=!line:~0,%keylen%!

if !linestart!==%key% (
set value=!line:~%eqsign%!
goto output_value
)
)

:: this will erase existing %tmp_dir%\new.ini and %tmp_dir%\new.txt files

:output_value
echo Outputting value to ini file
echo server=%value% > %tmp_dir%\new.ini
echo Outputting value to text file
echo The value is: %value% > %tmp_dir%\new.txt
goto eof

:eof
echo Press any key to quit
pause > NUL
goto blackhole

:blackhole


And there you have it!

Some obvious improvements could be:
- setting the key dynamically (this also means computing the key length on the fly).
- including adequate behaviour if the property definitions include spaces
(e.g. server = 192.0.2.42)

Thoughts?

Thursday, 31 July 2008

Using help to help yourself (part 2): publishing batch help information in HTML format

Well, it took quite a bit of head-scratching but here it is: a batch script that outputs information about commands in HTML format.

This is the code (NOTE: works with french accented words)

[commands_site.bat]

@echo off

:init
setlocal enabledelayedexpansion
set out_dir=site
set page_sub=pages
set page_dir=%out_dir%\%page_sub%
if not exist %page_dir% mkdir %page_dir%
goto create_site

:create_site
set ifile=%out_dir%\index.html
> %ifile% echo ^<html^>^<head^>^<title^>Commands index^</title^>^</head^>
>> %ifile% echo ^<body^>
for /F "tokens=1" %%C in ('help') do (
call :set_is_command %%C
if "!is_command!"=="1" (
echo Handling: %%C
set cfile=%page_dir%\%%C.html
>> %ifile% echo ^<a href="%page_sub%\%%C.html"^>%%C^</a^>^<br/^>
:: set cfile=CON
> !cfile! echo ^<html^>^<head^>^<title^>%%C^</title^>^</head^>
>> !cfile! echo ^<body^>^<h2^>%%C^</h2^>^<pre^>
for /F "delims=" %%T in ('help %%C') do (
set str=%%T
set str=!str:…=^&agrave;!
set str=!str:‚=^&eacute;!
set str=!str:Š=^&egrave;!
set str=!str:ˆ=^&ecirc;!
set str=!str:‰=^&euml;!
set str=!str:Œ=^&icirc;!
set str=!str:‹=^&iuml;!
set str=!str:“=^&ocirc;!
set str=!str:—=^&ugrave;!
set str=!str:–=^&ucirc;!
set str=!str:‡=^&ccedil;!
set str=!str:ÿ=^&nbsp;!
>> !cfile! echo !str!
)
>> !cfile! echo ^<br/^>^<br/^>
>> !cfile! echo ^<a href="../index.html"^>Back to index/Retour ^&agrave; l'index^</a^>
>> !cfile! echo ^</pre^>^</body^>^</html^>
)
)
>> %ifile% echo ^</body^>
>> %ifile% echo ^</html^>

goto end

:set_is_command
set name=%~1
set is_command=1
if not "%name%"=="" (
set num=1
for /F "usebackq tokens=1 delims=ABCDEFGHIJKLMNOPQRSTUVWXYZ" %%W IN ('%name%') do (
set num=0
)
set is_command=!num!
)
goto blackhole

:end
echo Press any key to quit...
pause > NUL

:blackhole

So, how does it work?

One
We enable delayedexpansion. This allows us to dynamically set variables in FOR loops.

Two
We prepare the output directories (mkdir). The root of the "site" is the site directory (this is where the site index will get stored). In this directory, a subdirectory is created which will hold all the pages (one for each command): the pages subdirectory.

Three
A loop (for /F "tokens=1" %%C in ('help')...) is used to loop through all the lines output by the help command. Each command is output starting with the command name and one or more lines of short explanations like the following example shows:

VERIFY Indique à Windows 2000 s'il doit ou non vérifier que les fichiers
sont écrits correctement sur un disque donné.

Notice the accented characters shown in the explanation (é, à).

Four
Obviously we only want to retrieve the command names (e.g. VERIFY) and nothing else. To do this we must check the first token of every line. In our case the first token will be VERIFY for the first line, and "sont" for the second line. Only the first of these two tokens is an actual command name. Fortunately, it has only uppercase letters.
The set_is_command subroutine makes sure the is_command variable is set to 1 if the token is a command (i.e. all uppercase letters) or 0 if the token isn't (one or more lowercase letters e.g. "sont").

Five
The script will output: one file for each command (containing its detailed help information) and an index file which will reference all these command pages.
For every command name, we:
- create a link in the index file
- create a file containing the detailed information (the result of help %commandname%)

Six
Notice there is a strange section with a few lines like:
set str=!str:Œ=^&icirc;!

At first, when I tried to output the result of 'help %commandname%' to an HTML file, the accented characters got replaced by different characters. For instance: "é" was shown as ",", "è" was shown as "Š", and so on and so forth. After some Googling and much head-scratching, I came up with this.
The idea is to replace the "bad" character with a character which will give me the desired result. Because I am working with HTML a good way to do this is to replace these accented characters with the corresponding HTML entities. Thus, é becomes &eacute;, à becomes &agrave;, etc.
I used a simple replacement syntax set str=!str:S=R! where S represents what you're searching for and R represents the desired replacement. Neat little trick.

There is a catch however. To work properly with accented characters, you need to open the batch file using EDIT (cmd > EDIT). If you open the above code using EDIT you will find that "…" becomes "à", "‚" becomes "é", "Š" becomes "è", etc. Once you have finished entering the accented characters, you can then revert to notepad for instance but the characters will look "strange" (i.e. as in the example above).
I guess you could do exactly the same with text, by typing the accented characters in notepad (for instance), then opening the file in EDIT. The notepad characters will look weird in EDIT but you can then type in EDIT the original characters to be replaced with the "weird" notepad characters using the S=R syntax. I haven't tried this but I expect it works.

Well, I think that's it. I hope someone will find this useful!

Thoughts?

Wednesday, 30 July 2008

Batch programming: using help to help yourself

Nothing I know of can quite beat the Linux/Unix "man" pages but here's a quickie on how to use the help command from the Windows command prompt.

Step 1: start the prompt (Start -> Run -> (type) cmd -> Enter)

Step 2: type help

cmd> help

This displays a list of available batch commands.

Step 3: get help on command of your choice (e.g. "FOR")

cmd> help for


Reading all of this in black and grey is pretty tedious, so I have started on a script that will output all these command in HTML format. Run it once and it will create a folder containing:
- an link index to all the commands
- one page per command with the relevant details

I currently have two major problems with this:
1. Trailing "spaces": I can't seem to remove trailing spaces successfully (not even sure they really are spaces)
[EDIT: PROBLEM 1 SOLVED, shall post code tomorrow]
2. Accented characters: I am using French, and accented characters are output as anything but what they should be. For instance "é" is output ",", etc. and I have yet to find a full-DOS solution to this problem.
[EDIT: PROBLEM 2 SOLVED, shall post code tomorrow]

Any suggestions more than welcome regarding these two issues =)

Tuesday, 29 July 2008

Batch programming tip#15: Getting file information

This example speaks for itself I think. You can obviously also use it in FOR loops or subroutines. It show how to retrieve lots of useful information about files (in this exemple the first argument).

[info.bat]

@echo off

:init_vars
if [%1]==[] goto what_file
if not exist %1 goto what_file
goto show_info

:show_info
echo.
echo General information
echo -------------------
echo Fully qualified name (%%~f1): %~f1
echo Drive letter (%%~d1): %~d1
echo Path (%%~p1): %~p1
echo File name (%%~n1): %~n1
echo File extension (%%~x1): %~x1
echo Date time (%%~t1): %~t1
echo Size (%%~z1): %~z1
echo File attributes (%%~a1): %~a1
goto show_combinations

:show_combinations
echo.
echo Some possible combinations
echo --------------------------
echo Drive and path (%%~dp1): %~dp1
echo Filename and extension (%%~nx1): %~nx1
echo Path using short names (%%~fs1) : %~fs1
echo.
goto eof

:what_file
echo Please provide valid file.
goto eof

:eof
echo Press any key to quit
pause > NUL


Simply call it using something like:

[info_call.bat]

@echo off
call info test_file_info.longext


These allow you to get: file size, date time, etc. Really useful stuff =D.

Have fun!

Sunday, 27 July 2008

Batch programming tip#14: The difference between :: and REM

Both REM and :: are commonly used to "comment out" a line in batch files, so what's the difference between them?

REM is the true "Remark" command. In other words it is treated as such and interpreted.

::, on the other hand, is an invalid label (a label starts with a colon) and is therefore simply skipped.

What this means is using REM is slower than using :: because :: means the line is skipped and the next is interpreted whereas with REM the line isn't skipped in the first place.

Thoughts?

Friday, 25 July 2008

Batch programming tip#13: Using setlocal enabledelayedexpansion

Delayed expansion is pretty tricky to explain. It basically means you are making sure that your variable is evaluated as many times as necessary and not just once (as would normally be the case).

The typical use for this is when using a "for" command. Without delayed expansion, variables do not appear to get set correctly. Why? Because they are evaluated once for the for command (rather than each time you loop) which results in apparently strange behaviour.

Example:

@echo off

:action
set num=0
for /l %%N IN (1,1,9) do (
echo %num%
set /a num=%num%+1
)
goto show_result

:show_result
echo Num is actually now worth: %num%
goto eof

:eof
echo Press any key to quit...
pause > NUL
goto blackhole

:blackhole

The for /l %%N IN (1,1,9) do command basically creates a loop from 1 to 9 with a step of 1 (so nine passes).
Anyhow, anyone would go crazy trying to debug this thing: it outputs nine zeros and a total worth of 1!

Enter delayed expansion however and things get back to normal:

@echo off

:init_sys
setlocal enabledelayedexpansion

:action
set num=0
for /l %%N IN (1,1,9) do (
echo !num!
set /a num=!num!+1

)
goto show_result

:show_result
echo Num is actually now worth: %num%
goto eof

:eof
echo Press any key to quit...
pause > NUL
goto blackhole

:blackhole

Notice we use the exclamation mark instead of % to reference variables within the for loop. This makes sure the variable is reassessed every time we use it.

I have written a short example below with a loop inside a loop. It loops through a sentence and shows every word separately using a call to an appropriate subroutine.


@echo off

:init_sys
setlocal enabledelayedexpansion

:init_vars
set text=The quick brown fox jumps over the lazy dog

:action
echo Displaying text using %%: %text%
echo Displaying text using ^^!: !text!

for /l %%N IN (1,1,9) do (
call :get_substr %%N "%text%"
echo Token: !strtok!
)
goto eof

:get_substr
set token=%~1
set string=%~2

for /F "usebackq tokens=%token% delims= " %%w in ('!string!') do (
set strtok=%%w
)
goto blackhole

:eof
echo Press any key to quit...
pause > NUL
goto blackhole

:blackhole

Note that if you don't use the delayed expansion properly (e.g. in the second for loop: '!string!') all hell will break loose... I know because I tried :D

The second use of delayed expansion is to nest variables like so:

@echo off

:init_sys
setlocal enabledelayedexpansion

:init_vars
set text=The quick brown fox jumps over the lazy dog

:action
for /l %%N IN (1,1,9) do (
call :getchars %%N
)
goto eof

:getchars
set num=%~1
echo !text:~0,%num%!
goto blackhole

:eof
echo Press any key to quit...
pause > NUL
goto blackhole

:blackhole

What this script does is successively retrieves N (N being 1 to 9) number of characters from our sentence "The quick brown fox jumps over the lazy dog".
To do this we nest the %num% variable in our "substring" notation:
!text:~0,%num%!

Cool.

Thoughts?

Sunday, 20 July 2008

Batch programming tip#12: Creating a timestamp

Now we can substring, creating a timestamp is really easy.

This is one simple way of doing this using the %date% and %time% system variables to create timestamped files.


@echo off

:create_file
call :get_timestamp
type NUL > %timestamp%.file
goto eof

:get_timestamp
set d_stamp=%date:~11%%date:~8,2%%date:~5,2%
set t_stamp=%time:~0,2%%time:~3,2%%time:~6,2%%time:~9%
set timestamp=%d_stamp%%t_stamp%
goto blackhole

:eof
echo Press any key to quit...
pause > NUL
goto blackhole

:blackhole

(We reverse year, month and day so that the files are naturally sorted in the 'right' order.)

The create_file section retrieves the timestamp (e.g. 2008071719410698) created by the get_timestamp subroutine and uses it to create an empty file. Obviously this can have multiple uses like timestamping log information for instance.

(Note: day and month probably appear in a different order according to sytem locale.)

Thoughts?

Saturday, 19 July 2008

Batch programming tip#11: Using The Substring Equivalent

As you know, most (all?) programming languages provide a substring() method of some sort which allows you to retrieve part of a string variable.

To do this in batch you can use the following syntax:
%var:~start% or
%var:~start,length%
where start is the index of the first character to retrieve (the first character in a string is indexed 0) and length is the length of the substring to retrieve. If no length is given the whole remaining string is shown.

In this example, we use a system variable %date% which holds the current system date and then echo the current system month and year.

@echo off

:get_year
echo System date: %date%
echo System month: %date:~8,2%
echo System year: %date:~11%
goto eof

:eof
echo Press any key to quit...
pause > NUL
goto blackhole

:blackhole


You can also use this method 'backwards'. Assume we didn't know the length of the %date% variable string, and wanted to retrieve the four last characters which represent the year.
We could then use the following syntax: %date:~-4% with a minus preceding the 4. This moves us back 4 characters from the end of the string, then (because no length has been specified) returns all the remainder until the end of the string. This is equivalent to: %date:~-4,4%

The drawback here is you cannot dynamically set the 'start' and 'length'. For this we need to use delayed expansion, which I'll get back to in a later post!

Until then, thoughts?

Friday, 18 July 2008

Batch Programming Tip#10: Making and calling a subroutine (part 2)

Let's see how can pass arguments to our get_date subroutine to change date format. For instance, we will be able to choose whether the day or month comes first in our output string and which separator (if any) we wish to use.
Beware that date /T is probably locale dependent. On my system the date is output in the following format 'day. dd/mm/yyyy' e.g. mon. 14/07/2008


@echo off

:show_date
call :get_date / 0 1
echo Date: %_date%
goto eof

:get_date
set delim=%~1
set order=%~2
set show_day=%~3

echo delim=%delim% and order=%order% and show_day=%show_day%

for /F "tokens=1,2,3,4 delims=/ " %%d in ('date /T') do (
set day=%%d
set dd=%%e
set mm=%%f
set yyyy=%%g
)

set _date=%dd%%delim%%mm%%delim%%yyyy%
if "%order%"=="1" set _date=%mm%%delim%%dd%%delim%%yyyy%
if "%show_day%"=="1" set _date=%day% %_date%
goto blackhole

:eof
echo Press any key to quit...
pause > NUL
goto blackhole

:blackhole


The get_date subroutine has changed considerably.

First, we get three possible arguments: delimiter, order (either day/month or month/day) and show_day (whether or not to show the day: 'mon.' for instance). You retrieve the arguments in the same way as you would for batch command-line arguments (using %~1, etc.).

These arguments are appended to the call to the subroutine: call :get_date / 0 1.

Second, we split the date string into four parts day (mon.), dd (14), mm (07), yyyy (2008).

Finally, we build the %_date% variable while taking into account the various arguments. If %order% is set to 1 we reverse dd and mm order. If show_day is set to 1, we prefix the date with the day.

That's it.

Thoughts?

Thursday, 17 July 2008

Batch Programming Tip#10: Making and calling a subroutine (part 1)

It looks like quite a few people are wondering how to write a subroutine, and how to pass it arguments. So let's write a small subroutine. You can't actually 'return' a value from the subroutine in the usual sense of the term. You can however set one or more variables within the subroutine which can then be used by the caller.

Let's imagine we need to write a subroutine that will retrieve the current date for us.

Let's start our batch by writing the following subroutine which will compute the date and store it in the %_date% variable.

@echo off

:get_date
for /F "tokens=2 delims= " %%d in ('date /T') do (
set _date=%%d
)
goto blackhole

:blackhole

What happens here is a slightly more complex for /F construct than we saw previously.
date /T outputs the current date, for instance as follows: mon. 14/07/2008
The for construct then effectively splits the string using the space character as the delimiter (this will leave us with 2 tokens: 'mon.' and '14/07/2008' but without the quotes). It then takes the second token (tokens=2) which is stored in %%d. Neat!

Obviously, if you run this script 'as-is', you won't actually 'see' anything happen, although the script will have computed the 'date' and stored it in the %_date% variable.

I do have an inkling that date format varies according to system locale. For instance you may find that on some systems you will output day/month/year and on others month/day/year according to your country/language settings.

Right, now let's add in some script to call the subroutine.


@echo off

:show_date
call :get_date
echo Date: %_date%
goto eof

:get_date
for /F "tokens=2 delims= " %%d in ('date /T') do (
set _date=%%d
)
goto blackhole

:eof
echo Press any key to quit...
pause > NUL
goto blackhole

:blackhole

Calling the subroutine is done in much the same way as calling an external batch but with an extra colon: call :get_date. This sets the %_date% variable which can then be shown from within the calling routine.

Note the importance of the 'goto blackhole' instruction at the end of the subroutine, this is what makes you 'return' to the calling code. You can alternatively use goto:EOF or goto :EOF. (Note that this is NOT the same as goto eof without the colon, which leads to the "Press any key" section of this script.)

One way to improve our subroutine would be to add arguments to allow for various date formats.

Thoughts?

Wednesday, 16 July 2008

Batch programming tip#09: Using FOR /D

This is a basic variation of the for loop. Add the /D modifier to loop through directories.

The following script shows all the subdirectories of the current directory (the directory the batch is running from).

@echo off

:action
for /D %%l in (*) do (
echo Directory: %%l
)
goto eof

:eof
echo Press any key to close window...
pause > nul
goto blackhole

:blackhole


Let's simply list all directories and all files in those directories:

@echo off

:action
for /D %%l in (*) do (
echo Directory: %%l
cd %~dp0\%%l
for %%f in (*.*) do (
echo File: %%f
)

)
goto eof

:eof
echo Press any key to close window...
pause > nul
goto blackhole

:blackhole

Well, that's it for now.

Thoughts?

Tuesday, 15 July 2008

Batch programming tip#08 (part 3): Reading from a file - Looping

This post will bring an end (I think) to this thread about file reading using batch.

To use the loop command on a file we simply add /F in our FOR loop construct like so:

@echo off

:init_vars
if exist file1.txt goto action
echo Oops. file1.txt doesn't exist. Please create it or change file name.
goto eof

:action
for /F %%l in (file1.txt) do (
echo Content: %%l
)
goto eof

:eof
echo Press any key to close window...
pause > nul
goto blackhole

:blackhole

This will probably work with most configuration files you might use. There is one additional parameter that's really useful though, especially if your lines contain spaces. The FOR loop will by default only return the first token up to a delimiter character. The default delimiter characters are space and tab. This means the script above will only return the first word of any line containing spaces.

To avoid this (usually unwanted) behaviour, use the delims parameter and set it to empty as in the following code:

@echo off

:init_vars
if exist file1.txt goto action
echo Oops. file1.txt doesn't exist. Please create it or change file name.
goto eof

:action
for /F "delims=" %%l in (file1.txt) do (
echo Content: %%l
)
goto eof

:eof
echo Press any key to close window...
pause > nul
goto blackhole

:blackhole


Notice how we have added to our for construct:
for /F "delims=" %%l in (file1.txt) do

You can set "delims=" to whatever you want in effect, you could for instance use comma instead: "delims=,".

Well, I think that's it, you can of course take file reading much further if you want. In that case, you might want to check Rob van der Woude's comprehensive page about NT FOR syntax. Enjoy!

More shortly about how to loop through directories.

Thoughts in the meantime?

Monday, 14 July 2008

Batch programming tip#08 (part 2): Reading from a file - Looping

So, let's see how we can loop through information.
The following script is the same as the previous but I have added a loop construct which will loop through our file_content variable (the first line of the file).

@echo off

:init_vars
if exist file1.txt goto action
echo Oops. file1.txt doesn't exist. Please create it or change file name.
goto eof

:action
set /P file_content=<file1.txt
for %%l in (%file_content%) do (
echo Content: %%l
)
goto eof

:eof
echo Press any key to close window...
pause > nul
goto blackhole

:blackhole

The loop construct is simple: for %%varname in (%var%) do ( ..[action]..)
The parentheses around the %var% are not in there just for form, you really need to remember them or your batch will crash.

To test it try using a file that contains a first line with spaces in it (e.g. The quick brown fox jumps over the lazy dog) and you will see that each word of the first line of the file will appear on a line of its own.

Excellent, the next step will be to loop through all the lines in a file.

Thoughts in the meantime?

Sunday, 13 July 2008

Batch programming tip#08: Reading from a file

Reading from file can sometimes be really useful. For example, you could imagine one process was to output lots of file names to a given file (let's call it file1.txt) and then that our batch would jump in there and retrieve those file names and print up whatever is in them (obviously in a real-world case scenario, you would want to handle the files and do something with them, e.g. archive them to a different location or whatever).

To read content from a file, we set a variable using /P and the < sign after the usual = sign.

The following code does this.

@echo off

:init_vars
set /P file_content=<file1.txt
goto action

:action
echo File content: %file_content%
goto eof

:eof
echo Press any key to close window...
pause > nul
goto blackhole

:blackhole

Note that if file1.txt doesn't exist an error message will show and the variable %file_content% will be empty.

Hey presto, we got something out of the file. This is great... except: we are only getting hold of the first line.

In the two following posts, I will explain the loop construct and how to use it to read all the lines from the file.

Thoughts in the meantime?

Saturday, 12 July 2008

Batch tip#07 part 2: comparing files by size

Now we have seen how to retrieve the length of a file passed as argument, let's see how we can use this.

The code below does the following:

1. Command-line check
The process checks for command-line arguments. It expects two existing files otherwise shows an error.
To check whether a file exists, simply use if exist %file%.

2. Compare sizes
The batch retrieves and compares argument file sizes. To do this we use %~z1 and %~z2 which return the file sizes of command line arguments 1 and 2 respectively.

3. Take action
Finally, it outputs an adequate message. This is obviously the bit where you should include appropriate actions.

The code


@echo off

:param_check
if "" == "%1" goto invalid_call
if "" == "%2" goto invalid_call
goto file_one

:file_one
if exist %1 goto file_two
set file_path=%1
goto show_error

:file_two
if exist %2 goto run_content
set file_path=%2
goto show_error

:run_content
if %~z1==%~z2 goto same_size
if %~z1 LSS %~z2 goto first_smaller
goto second_smaller

:same_size
echo Both files are of same size.
goto eof

:first_smaller
echo %1 is smaller than %2
goto eof

:second_smaller
echo %2 is smaller than %1
goto eof

:show_error
echo File not found: "%file_path%"
goto eof

:invalid_call
echo Please call with the following parameters:
echo [1] the first file name
echo [2] the second file name
goto eof

:eof
echo Press any key to close window...
pause > nul
goto blackhole

:blackhole


To run this, simply use a second .bat file containing something like:

@echo off
call comp_files file1.txt file2.txt

Where file1.txt and file2.txt are replaced with the relative or absolute paths of the files your are comparing.

Simple as that!

Thoughts?

Thursday, 10 July 2008

Batch programming tip#07: Retrieving argument filesize

Imagine you are using a file as argument (this can also be %0 of course) and you would like to know the file's size in bytes.

This is an example of how to do this:

@echo off

:action
echo File size of currently running batch file: %~z0
goto eof

:eof
echo Press a key to quit...
pause > NUL
goto blackhole

:blackhole

Using %~z0 retrieves the file size of the currently running batch which should be 164 (unless of course you have added in or removed extra line breaks, comments, etc.)

One reason to use file size would be, for instance, you might want a batch to once use a given configuration file, but then use another the next time, and then to switch back to the first the time after that. If these configuration files are definitely of different size, you can use file size to operate the swap.

Voilà!

Thoughts?
Online Marketing
Add blog to our blog directory blog search directory Blog Directory Blogarama - The Blog Directory