Rob van der Woude's Scripting Pages

PHP based batch files

I sometimes reach the limit of the batch language's capabilities.
I know, it is possible to calculate a cosine with SET /A, but practical...?

Or how about an MD5 checksum of a string?

PHP, on the other hand, does have these functions available.
So why not use PHP in batch files?

Start by downloading and installing PHP.

Next copy the following code and save it as MD5.BAT:

@IF NOT "%~1"=="" PHP.EXE -r "print(md5('%~1'));"

Or if you did not add your PHP directory to the PATH:

@IF NOT "%~1"=="" FOR /F "tokens=2*" %%A IN ('REG Query HKLM\SOFTWARE\PHP /v InstallDir') DO @%%~sB.\PHP.EXE -r "print(md5('%~1'));"

I love these one-liners! 😉

A good reason to try and place the code in a single line is that it can be placed inside another FOR /F loop.
The MD5 example could be used in a FOR /F loop to get the result in an environment variable:

@IF NOT "%~1"=="" FOR /F %%A IN ('PHP.EXE -r "print^(md5^(\"%~1\"^)^)^;"') DO @SET MD5=%%A

Note that I left the IF statement outside the FOR /F loop.
There is no law against inclusion in the loop, but consider it best practice to keep the part between parentheses as "clean" as possible.
Likewise you would want to try and avoid nesting FOR /F loops. Even though

@IF NOT "%~1"=="" FOR /F %%C IN ('FOR /F "tokens=2*" %%A IN ^(^'REG Query HKLM\SOFTWARE\PHP /v InstallDir^'^) DO @%%~sB.\PHP.EXE -r "print^(md5^(\"%~1\"^)^)^;"') DO @SET MD5=%%C

may work, a "cleaner" method, if you insist on a one-liner, would be:

@IF NOT "%~1"=="" FOR /F "tokens=2*" %%A IN ('REG Query HKLM\SOFTWARE\PHP /v InstallDir') DO @FOR /F %%C IN ('%%~sB.\PHP.EXE -r "print^(md5^(\"%~1\"^)^)^;"') DO @SET MD5=%%C

Why I prefer the latter?
Try nesting each version in a third FOR /F loop and you'll understand: each level of nesting would require an extra "level" of escaping escape characters!

If you reach this level of complexity, consider making your code more readable by using subroutines.
They may slow down execution of the batch file, but they may save you lots of time if you need to do some maintenance on the code in, say, a year or so.

Now test it, run:

MD5.BAT password

If all went well, the batch file should return 5f4dcc3b5aa765d61d8327deb882cf99, the MD5 checksum value for the string password.

Running:

MD5.BAT PASSWORD

should return 319f4d26e3c536b5dd871bb2c52e3178.

Likewise we can write a batch file to calculate the SHA1 checksum of a string:

@IF NOT "%~1"=="" PHP.EXE -r "print(sha1('%~1'));"

Note that I avoid spaces in the actual PHP command following the -r switch.
I found out the hard way that with spaces the batch file becomes very unreliable. Enclosing the PHP command in doublequotes is supposed to fix that, but I did not get reliable results.

The options for "new technology" batch files are unlimited!

Binary to decimal conversion:

:: https://www.robvanderwoude.com/batchphp.php
:: Usage:  "bin2dec 1101" returns "13"
@PHP -r print(bindec(%~1));

OK, bad example, this can also be done using SET /A for numbers below 32768.
But how about binary to hexadecimal conversion?

:: https://www.robvanderwoude.com/batchphp.php
:: Usage:  "bin2hex 11001101" returns "0xCD"
@PHP -r print('0x'.strtoupper(dechex(bindec(%~1))));

Or decimal to binary?

:: https://www.robvanderwoude.com/batchphp.php
:: Usage:  "dec2bin 13" returns "1101"
@PHP -r print(decbin(%~1));

Examples

💾 Click the floppy disk or package (for third party scripts) 📦 icons to download the ZIPped sources

Click the question mark icons to view the MD5 and SHA1 checksums for the ZIPped sources

 

PHP based batch files
💾 Name Description Last modified
(yyyy-mm-dd)
Usage
💾 Bin2Dec.bat Converts specified binary number to decimal 2010-07-15 Bin2Dec 11110011 will return 243
💾 Bin2Hex.bat Converts specified binary number to hexadecimal 2010-07-15 Bin2Hex 11110011 will return 0xF3
💾 Cosine.bat Returns the cosine for the specified number of radians 2010-07-15 Cosine 3.14 will return -0.99999873172754
💾 CosineDeg.bat Returns the cosine for the specified number of degrees 2010-07-15 CosineDeg 180 will return -1
💾 CRC32.bat Returns the decimal CRC32 checksum for the specified string 2010-07-21 CRC32 "test" will return -662733300
💾 CRC32Hex.bat Returns the hexadecimal CRC32 checksum for the specified string 2010-08-13 CRC32Hex "test" will return 0xD87F7E0C
💾 Dec2Bin.bat Converts specified decimal number to binary 2010-07-15 Dec2Bin 243 will return 11110011
💾 Dec2Hex.bat Converts specified decimal number to hexadecimal 2010-07-15 Dec2Hex 243 will return 0xF3
💾 EasterPHP.bat Returns the Easter date for the current or specified year 2011-12-28 Easter 2025 will return Sunday, 20 April 2025
💾 Exp.bat Returns e raised to the power of the specified number 2010-07-21 Exp 1 will return 2.718281828459
Exp 5 will return 148.41315910258
💾 FPMath.bat Command line floating point calculations 2010-07-16 FPMath 12+2*3 will return 18
💾 Hex2Bin.bat Converts specified hexadecimal number to binary 2010-07-15 Hex2Bin 0xF3 will return 11110011
💾 Hex2Dec.bat Converts specified hexadecimal number to decimal 2010-07-15 Hex2Dec 0xF3 will return 243
💾 ISODate.bat Returns the date specified in year, week and day, in the requested format 2010-07-21 ISODate 2008 4 2  Ymd  will return 20080122
ISODate 2008 4 2 m/d/y will return 01/22/08
💾 LastDayOfMonth.bat Returns the number of days in the specified month 2010-07-21 LastDayOfMonth 2 2008 will return 29
LastDayOfMonth 2 2009 will return 28
💾 Ln.bat Returns the natural logarithm of the specified number 2010-07-21 Ln 100 will return 4.6051701859881
Ln 2.71828182845905 will return 1
💾 Log10.bat Returns the base-10 logarithm of the specified number 2010-07-21 Log10 100 will return 2
Log10  25 will return 1.397940008672
💾 Max.bat Returns the largest of the specified numbers 2010-07-21 Max 2 -5 43 0 will return 43
💾 MD5.bat Returns the MD5 hash for the specified string 2010-07-21 MD5 "test" will return 098f6bcd4621d373cade4e832627b4f6
💾 MD5Perl.bat Uses Perl to return the MD5 hash for the specified string 2010-08-01 MD5Perl "test" will return 098f6bcd4621d373cade4e832627b4f6
💾 Min.bat Returns the smallest of the specified numbers 2010-07-21 Min 2 -5 43 0 will return -5
💾 Pow.bat Returns first number raised to the power of second one 2010-07-21 Pow 10 3 will return 1000 (103)
Pow  5 2 will return   25 (52)
💾 readword.php Read a Word document and show its plain text either in a browser or in a console 2012-10-25 Not a batch file, but it can be used by batch files:
php.exe readword.php wordfile.doc for command line use
START http://domain.example/readword.php for interactive use in a browser
Requires MS Office to read the Word document, plus the following entry in your PHP.INI:
[COM_DOT_NET]
extension=php_com_dotnet.dll
💾 RFaR.bat Regex Find and Replace 2010-07-30 RFaR /T/i P "test string" will return Pest sPring
RFaR "/img(_?)(\d{4,5})\.jpg/i" Foto${2}.jpg IMG_8094.JPG will return Foto8094.jpg
💾 SFaR.bat Simple Find and Replace 2010-07-21 SFaR pin needle "a pin in a haystack" will return "a needle in a haystack"
💾 SHA1.bat Returns the SHA-1 hash for the specified string 2010-07-21 SHA1 "test" will return a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
💾 SHA1Perl.bat Uses Perl to return the SHA-1 hash for the specified string 2010-08-01 SHA1Perl "test" will return a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
💾 Sine.bat Returns the sine for the specified number of radians 2010-07-15 Sine 1.54 will return 0.99952583060548
💾 SineDeg.bat Returns the sine for the specified number of degrees 2010-07-15 SineDeg 90 will return 1
💾 SortDate_PHP.bat Returns the current date and time in YYYYMMDD HHmmss format 2010-07-21 SortDate_PHP will return something like 20240420 161330
💾 Sqrt.bat Returns the square root of the specified number 2010-07-21 Sqrt 100 will return 10
Sqrt  25 will return  5
💾 Tangent.bat Returns the tangent for the specified number of radians 2010-07-21 Tangent 3.1416 will return -7.3464102066436E-6
💾 TangentDeg.bat Returns the tangent for the specified number of degrees 2010-07-21 TangentDeg 45 will return 0.70710678118655
💾 TimeShift.bat Convert date/time from any timezone to local date/time 2011-04-09 TimeShift Europe/Amsterdam 2018-12-13 9:45 AM PST will return 13-12-2018 18:45:00 or 12/13/2018 18:45:00 (local time for Europe/Amsterdam)
💾 UniqueChars.bat Returns a sorted list of all characters used in the specified string 2010-07-21 UniqueChars "the quick brown fox jumps over the lazy dog" will return " abcdefghijklmnopqrstuvwxyz"
💾 WANIP.bat Returns your WAN IP address 2018-12-13 Idea: Stan Littlefield
💾 WeekPHP.bat Returns the ISO week number for the specified date 2011-03-01 Idea: Stan Littlefield
💾 XPath.bat Displays the results of an XPath expression against an XML file 2022-11-04 XPath.bat example.xml "//*/@*" will display all attribute values for all nodes

Using PHP only

You don't really need to embed PHP code in batch files, PHP can handle command lines quite well.

Let's take the MD5 function. An MD5.PHP for command line use would look like this:

#! php.exe -q
<?php
if ( $argv[1] ) {
	print( md5( $argv[1] ) );
}
?>

You can run it using the command PHP MD5.PHP "string" to get the MD5 checksum for "string".

Or you can define a file type association for PHP and just run the command MD5.PHP "string" to get the checksum.

Even the definition of the file type association can be automated. Just run the following batch code once:

FOR /F "tokens=1* delims==" %%A IN ('ASSOC .php') DO SET PHPFileType=%%B
FOR /F "tokens=2*" %%A IN ('REG Query HKLM\SOFTWARE\PHP /v InstallDir') DO (
	FTYPE "%PHPFileType%"=%%~sB.\PHP.EXE "%1"
)

Combine the power of PHP with WMI

Definitely unsuited for one-liners, but you can use PHP based WMI scripts.

Create the following script to list some monitor properties:

  1. <?php
  2. $wmi_object    = new COM( "winmgmts://./root/WMI" );
  3. $wmi_instances = $wmi_object-<ExecQuery( "SELECT * FROM WmiMonitorID" );
  4.  
  5. foreach ( $wmi_instances as $instance ) {
  6. 	print( "Active                 : {$instance->Active}\n" );
  7. 	print( "InstanceName           : {$instance->InstanceName}\n" );
  8. 	print( "ManufacturerName       : " );
  9. 	if ( $instance->ManufacturerName ) {
  10. 		foreach ( $instance->ManufacturerName as $value ) {
  11. 			print( "{$value};" );
  12. 		}
  13. 	}
  14. 	print( "\n" );
  15. 	print( "ProductCodeID          : " );
  16. 	if ( $instance->ProductCodeID ) {
  17. 		foreach ( $instance->ProductCodeID as $value ) {
  18. 			print( "{$value};" );
  19. 		}
  20. 	}
  21. 	print( "\n" );
  22. 	print( "SerialNumberID         : " );
  23. 	if ( $instance->SerialNumberID ) {
  24. 		foreach ( $instance->SerialNumberID as $value ) {
  25. 			print( "{$value};" );
  26. 		}
  27. 	}
  28. 	print( "\n" );
  29. 	print( "UserFriendlyName       : " );
  30. 	if ( $instance->UserFriendlyName ) {
  31. 		foreach ( $instance->UserFriendlyName as $value ) {
  32. 			print( "{$value};" );
  33. 		}
  34. 	}
  35. 	print( "\n" );
  36. 	print( "UserFriendlyNameLength : {$instance->UserFriendlyNameLength}\n" );
  37. 	print( "WeekOfManufacture      : {$instance->WeekOfManufacture}\n" );
  38. 	print( "YearOfManufacture      : {$instance->YearOfManufacture}\n" );
  39. 	print( "\n" );
  40. }
  41. ?>

Save the file as wmimonitorid.php.

For PHP version 5.4.5 or later, the following modification in php.ini is required:

[COM_DOT_NET]
extension=php_com_dotnet.dll

Now run the following command:

php.exe -f wmimonitorid.php

(assuming php.exe is in the PATH)

The command's output may look like this:

Active                    : 1
InstanceName              : DISPLAY\SAM083A\7&cf6ea47&1&UID4194576_0
ManufacturerName          : 83;65;77;0;0;0;0;0;0;0;0;0;0;0;0;0;
ProductCodeID             : 48;56;51;65;0;0;0;0;0;0;0;0;0;0;0;0;
SerialNumberID            : 88;88;88;48;48;48;48;48;48;48;0;0;0;0;0;0;
UserFriendlyName          : 83;77;83;50;52;65;52;53;48;0;0;0;0;
UserFriendlyNameLength    : 13
WeekOfManufacture         : 41
YearOfManufacture         : 2011

Active                    : 1
InstanceName              : DISPLAY\SAM0467\7&cf6ea47&1&UID4194578_0
ManufacturerName          : 83;65;77;0;0;0;0;0;0;0;0;0;0;0;0;0;
ProductCodeID             : 48;52;54;55;0;0;0;0;0;0;0;0;0;0;0;0;
SerialNumberID            : 88;89;90;48;48;48;48;48;48;49;0;0;0;0;0;0;
UserFriendlyName          : 83;121;110;99;77;97;115;116;101;114;0;0;0;
UserFriendlyNameLength    : 13
WeekOfManufacture         : 12
YearOfManufacture         : 2009

Using Perl

Instead of PHP code embedded in batch files, you can also use Perl.

Let's take the MD5 function. A Perl based MD5Perl.bat would look like this:

@IF NOT "%~1"=="" perl.exe -MDigest::MD5=md5_hex -le "print md5_hex '%~1'"

Or for SHA-1:

@IF NOT "%~1"=="" perl.exe -MDigest::SHA1=sha1_hex -le "print sha1_hex '%~1'"

Caution

Dealing with command lines means not all characters are allowed.
Ampersands, single and double quotes, even spaces in arguments can break scripts.
Make sure to thoroughly test the scripts presented here, and your own, or in fact any script, before using them for "production".

Command line hash calculators for files:

Command line hash calculators for strings:


page last modified: 2022-11-04; loaded in 0.0727 seconds