Conditionals on steroids
Posted: 31 May 2014 11:57
I decided to share my little work that extends conditionals in batch scripts. I developed it just for fun. And I can say that the time I spent for it gave me some pleasure .
I put here the link to the source (not for advertisements but for those people who could be interested to read more).
https://github.com/ildar-shaimordanov/c ... r/when.bat
I believe that all of us know that conditionals
1. have a lot of lacks (impossible to express more complex conditionals with and/or as in the most of programming languages)
2. some checks are implemented in uncertain ways (check of attributes or existence of file or directory)
There are no revolutionary things but this implementation is more flexible, gives unified way for comparison/checking of different things (files, directories, strings).
Steroids based on conditional execution with && and || have been inspired by the test coming from unix sh/ksh/bash etc. Another thing came from Perl with two conditional operators if and unless (that simply means if not).
All stuff is implemented within the batch script test.bat. The common syntax is:
EXPR is a standard conditional expression or extended one (that I called "steroid").
commandThen will be executed when the EXPR is true
commandElse will be executed when the EXPR is false
This example is similar to the previous one but the sense is reversed: commandThen will be executed when EXPR is false and commandElse will be executed when EXPR is true.
Both commandThen and commandElse can be sets of commands wrapped within block. The good practice is to use blocks always. The previous example can be rewritten with blocks:
The script allows complex comparison in easy way:
CommandThen will be executed if both EXPR1 and EXPR2 are true. And commanElse otherwise.
commandThen will be executed if at least one of EXPR1 or EXPR2 is true.
That example above have little bit weird view (of course, they differ on usual IF constriction) but they allow express complex conditionals in simple way. Regular IF does not allow such a kind of shortness (two or more separate IFs, several labels and corresponding GOTOs).
All examples in this post are considering an external calling of test.bat. But we can embed test.bat within the script and simplify usage as in the following example:
Standard expressions
However the script implements many features that have came from another worlds it has kept the native conditionals as well. You always can write as follows:
But it's more interesting to consider extended expressions.
Extended file expressions
-a FILE
True if file exists.
-b FILE
True if file is drive.
-c FILE
True if file is character device.
-d FILE
True if file is a directory. Similar to -attr d.
-e FILE
True if file exists.
-f FILE
True if file exists and is a regular file.
-h FILE
True if file is a link. Similar to -attr l.
-L FILE
True if file is a link. Similar to -attr l.
-r FILE
True if file is read only. Similar to -attr r.
-s FILE
True if file exists and is not empty.
-w FILE
True if the file is writable, i.e. not read only.
-x FILE
True if the file is executable.
-attr ATTR FILE
True if ATTR is set for FILE.
The following attributes can be recognized:
-path FILE
True if FILE is listed in the PATH environment variable.
More file expressions
FILE1 -nt FILE2
True if FILE1 is newer than FILE2 (according to modification time). This operator is depending on the user-defined settings or locales, that means that the result of this comparison cannot be considered as reliable.
FILE1 -ot FILE2
True if FILE1 is older than FILE2 (according to modification time). This operator is depending on the user-defined settings or locales, that means that the result of this comparison cannot be considered as reliable.
Extended string expressions
-n STRING
True if STRING is not empty.
-z STRING
True if STRING is empty.
More string expressions
STACK -contains NEEDLE
True if STACK contains NEEDLE.
STACK -starts NEEDLE
True if STACK starts with NEEDLE.
STACK -ends NEEDLE
True if STACK ends with NEEDLE.
I put here the link to the source (not for advertisements but for those people who could be interested to read more).
https://github.com/ildar-shaimordanov/c ... r/when.bat
I believe that all of us know that conditionals
1. have a lot of lacks (impossible to express more complex conditionals with and/or as in the most of programming languages)
2. some checks are implemented in uncertain ways (check of attributes or existence of file or directory)
There are no revolutionary things but this implementation is more flexible, gives unified way for comparison/checking of different things (files, directories, strings).
Steroids based on conditional execution with && and || have been inspired by the test coming from unix sh/ksh/bash etc. Another thing came from Perl with two conditional operators if and unless (that simply means if not).
All stuff is implemented within the batch script test.bat. The common syntax is:
Code: Select all
call when :if EXPR && commandThen || commandElse
commandThen will be executed when the EXPR is true
commandElse will be executed when the EXPR is false
Code: Select all
call when :unless EXPR && commandThen || commandElse
Both commandThen and commandElse can be sets of commands wrapped within block. The good practice is to use blocks always. The previous example can be rewritten with blocks:
Code: Select all
call test :if EXPR && (
commandThen1
commandThen2
) || (
commandElse1
commandElse2
)
Code: Select all
call when :if EXPR1 && call test :if EXPR2 && commandThen || commandElse
Code: Select all
call when :if EXPR1 || call when :if EXPR2 && commandThen || commandElse
That example above have little bit weird view (of course, they differ on usual IF constriction) but they allow express complex conditionals in simple way. Regular IF does not allow such a kind of shortness (two or more separate IFs, several labels and corresponding GOTOs).
All examples in this post are considering an external calling of test.bat. But we can embed test.bat within the script and simplify usage as in the following example:
Code: Select all
call :if EXPR && commandThem
Standard expressions
However the script implements many features that have came from another worlds it has kept the native conditionals as well. You always can write as follows:
Code: Select all
call when :if "%~1" == "help" && (
call :help
goto :EOF
)
Extended file expressions
-a FILE
True if file exists.
-b FILE
True if file is drive.
-c FILE
True if file is character device.
-d FILE
True if file is a directory. Similar to -attr d.
-e FILE
True if file exists.
-f FILE
True if file exists and is a regular file.
-h FILE
True if file is a link. Similar to -attr l.
-L FILE
True if file is a link. Similar to -attr l.
-r FILE
True if file is read only. Similar to -attr r.
-s FILE
True if file exists and is not empty.
-w FILE
True if the file is writable, i.e. not read only.
-x FILE
True if the file is executable.
-attr ATTR FILE
True if ATTR is set for FILE.
The following attributes can be recognized:
Code: Select all
Attribute Expansion
FILE_ATTRIBUTE_DIRECTORY d--------
FILE_ATTRIBUTE_READONLY -r-------
FILE_ATTRIBUTE_ARCHIVE --a------
FILE_ATTRIBUTE_HIDDEN ---h-----
FILE_ATTRIBUTE_SYSTEM ----s----
FILE_ATTRIBUTE_COMPRESSED -----c---
FILE_ATTRIBUTE_OFFLINE ------o--
FILE_ATTRIBUTE_TEMPORARY -------t-
FILE_ATTRIBUTE_REPARSE_POINT --------l
FILE_ATTRIBUTE_NORMAL ---------
True if FILE is listed in the PATH environment variable.
More file expressions
FILE1 -nt FILE2
True if FILE1 is newer than FILE2 (according to modification time). This operator is depending on the user-defined settings or locales, that means that the result of this comparison cannot be considered as reliable.
FILE1 -ot FILE2
True if FILE1 is older than FILE2 (according to modification time). This operator is depending on the user-defined settings or locales, that means that the result of this comparison cannot be considered as reliable.
Extended string expressions
-n STRING
True if STRING is not empty.
-z STRING
True if STRING is empty.
More string expressions
STACK -contains NEEDLE
True if STACK contains NEEDLE.
STACK -starts NEEDLE
True if STACK starts with NEEDLE.
STACK -ends NEEDLE
True if STACK ends with NEEDLE.