Skip to content

Instantly share code, notes, and snippets.

@juntalis
Created November 21, 2016 15:13
Show Gist options
  • Save juntalis/63720b9c9ec82eaa906129b4d4f4972d to your computer and use it in GitHub Desktop.
Save juntalis/63720b9c9ec82eaa906129b4d4f4972d to your computer and use it in GitHub Desktop.
Common-use functions for batch
@echo off
:dirname
rem Given a filepath, resolve the absolute filepath of its parents folder.
rem \param [out] %1 - The variable name to output the results to.
rem \param [in] %2 - The filepath that we'll be operating on.
call set "%~1=%%~dp2"
call set "%~1=%%%~1:~0,-1%%"
goto :EOF
:filename
rem Given a filepath, extract the filename. (name and file extension)
rem \param [out] %1 - The variable name to output the results to.
rem \param [in] %2 - The filepath that we'll be operating on.
call set "%~1=%~nx2"
goto :EOF
:basename
rem Given a filepath, extract the basename. (name without file extension)
rem \param [out] %1 - The variable name to output the results to.
rem \param [in] %2 - The filepath that we'll be operating on.
call set "%~1=%~n2"
goto :EOF
:abspath
rem Resolve the absolute filepath to a file or folder.
rem \param [out] %1 - The variable name to output the results to.
rem \param [in] %2 - The filepath that we'll be operating on.
call set "%~1=%~f2"
goto :EOF
:which
rem Get the path of the program in arg 2 and set the variable who's
rem name was specified in the first argument.
rem \param [out] %1 - The variable name to output the executable path to.
rem \param [in] %2 - The executable name to search for.
call set "%~1=%~f$PATH:2"
goto :EOF
:trimslashes
rem Trims all trailing '/' and '\')from a variable.
rem \param [inout] %1 - The name of the variable we'll be operating on.
call set "__C=%%%~1:~-1%%"
if not "%__C%x"=="\x" if not "%__C%x"=="/x" (set "__C=" & goto :EOF)
call set "%~1=%%%~1:~0,-1%%"
goto trimslashes
:strlen
rem Determine the length of the string specified in the second argument.
rem \param [out] %1 - The variable name to output the results to.
rem \param [in] %2 - The subject text that we will be measuring.
setlocal
set _STRLEN_BUFFER_=%~2
set /A _STRLEN_LENGTH_=0
:strlen_loop
if "%_STRLEN_BUFFER_%x"=="x" goto strlen_continue
set _STRLEN_CHAR_=%_STRLEN_BUFFER_:~0,1%
set /A _STRLEN_LENGTH_ += 1
set _STRLEN_BUFFER_=%_STRLEN_BUFFER_:~1%
goto strlen_loop
:strlen_continue
endlocal & call set %~1=%_STRLEN_LENGTH_%
goto :EOF
:rreplace
rem Replaces recursively.
rem \param [out] %1 - The variable name to output the results to.
rem \param [in] %2 - The subject text to search and replace through.
rem \param [in] %3 - The substring to search for in %2.
rem \param [in] %4 - The replacement text to substitute when %3 is found.
call set "%~1=%~2"
verify>nul
:rreplace_work
(call echo %%%~1%%|find "%~3")>nul 2>nul
if errorlevel 1 goto rreplace_done
verify>nul
call set "%~1=%%%~1:%~3=%~4%%"
goto rreplace_work
:rreplace_done
verify>nul
goto :EOF
:tolower
rem Subroutine to convert a variable VALUE to all lower case.
rem The argument for this subroutine is the variable NAME.
for %%C in ("A=a" "B=b" "C=c" "D=d" "E=e" "F=f" "G=g" "H=h" "I=i" "J=j" "K=k" "L=l" "M=m" "N=n" "O=o" "P=p" "Q=q" "R=r" "S=s" "T=t" "U=u" "V=v" "W=w" "X=x" "Y=y" "Z=z") do @call set "%~1=%%%~1:%%~C%%"
goto :EOF
:isdefined
rem Checks if a variable has a defined value.
if "%~1x"=="x" exit /B 1
if not defined %~1 exit /B 1
goto :EOF
:splitenv
rem Given an expandable environment variable such as PATH or PATHEXT,
rem split the variable into its individual lowercase components such that the
rem value of:
rem .COM;.BAT;.EXE
rem would expand into:
rem ".COM" ".BAT" ".EXE"
rem The resulting value should be suitable for using with the FOR command.
call set %~1=%%%~2:;=" "%%
call set %~1="%%%~1%%"
call :tolower "%~1"
goto :EOF
:whichex
rem Similar to the original which above, but with additional functionality
rem to use the PATHEXT variable when the executable is specified without a
rem file extension. (ex: Specifying cmd.exe as cmd)
rem \param [out] %1 - The variable name to output the executable path to.
rem \param [in] %2 - The executable name to search for.
setlocal
set _WHICHEX_TARGET_=%~2
call :which _WHICHEX_RESULT_ "%_WHICHEX_TARGET_%"
if exist "%_WHICHEX_RESULT_%" goto whichex_success
if not "%~x2x"=="x" goto whichex_failure
goto whichex_pathext
:whichex_testpath
rem Given a file basename and extension, see if we can find a matching
rem executable on the system PATH.
if errorlevel 1 exit /B %ERRORLEVEL%
call :which _WHICHEX_RESULT_ "%~1%~2"
if exist "%_WHICHEX_RESULT_%" exit /B 1
goto :EOF
:whichex_pathext
rem No file extension was found on our executable name. First we'll try
rem a search with no extension, (as it was specified) and if that fails,
rem we'll try the search again with each file extension in PATHEXT until
rem we find a match. (or run out of extensions)
call :splitenv _WHICHEX_PATHEXT_ PATHEXT
for %%E in (%_WHICHEX_PATHEXT_%) do @call :whichex_testpath "%~nx2" "%%~E"
rem When an executable is found, the errorcode is set to 1 to indicate success.
if errorlevel 1 goto whichex_success
rem If it's still zero at this point, that means we failed to find our executable.
goto whichex_failure
:whichex_success
rem We maanged to resolve the executable path, which is now stored in a
rem localized variable named _WHICHEX_RESULT_. Copy that value over to
rem our outgoing parameter and cleanup.
verify>nul
call set _WHICHEX_COPYCMD_=set "%~1=%_WHICHEX_RESULT_%"
endlocal & call %_WHICHEX_COPYCMD_%
goto :EOF
:whichex_failure
rem We failed to find the executable path based on the info given. Clean
rem up and report the error.
set _WHICHEX_RESULT_=
endlocal
call set %~1=%_WHICHEX_RESULT_%
exit /B 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment