The suggested new versions lose significant functionality compared to the original. They don't expand wildcards, nor do they normalize the path into a fully qualified path. They only make sure it doesn't end in \.
For example, given a path of
test.txt The original might come back with something like
C:\myDirectory\test.txt. The new versions just come back with
test.txtI have a solution that preserves the original functionality. But first some suggestions to improve the original:
1) Send the missing argument error messages to stderr instead of stdout.
2) The original exits the cmd shell if it is missing an argument. It is probably better just to exit the batch script.
3) You don't want to strip the final \ if the path represents the root directory. For example
C:\ (the root directory) has entirely different meaning than
C: (the current directory for C:). Rather than strip the last \, why not add a \ if the path represents a directory and the last character is not a \? In this way you can easily tell the difference between a file path and a directory path.
4) You don't want to get in the habit of defining a local PATH variable in your functions. It doesn't cause a problem in this case, but it will prevent you from executing an external command from within the function. Worse yet, if you forget to issue SETLOCAL, you will have corrupted your PATH for the remainder of your session!
Here is a modified version implementing the above suggestions:
Code: Select all
@echo off
:NormalizeFilespec - <var:Output> <"path":input> -- "normalize + guarantee \ at end of directory path"
:: returns (additional) error(123) if filespec(file/path) is not existing.
IF "%~1" EQU "" >&2 ECHO Err(:NormalizeFilespec): missing first parameter.&EXIT /b 96001
IF "%~2" EQU "" >&2 ECHO Err(:NormalizeFilespec): missing second parameter.&EXIT /b 96002
SETLOCAL
set "fpath=%~f2"
if "%fpath:~-1%" neq "\" dir "%fpath%\." >nul 2>nul && set "fpath=%fpath%\"
if not exist "%fpath%" (set "err=123") else (set "err=0")
ENDLOCAL & set "%~1=%fpath%" & EXIT /b %err%
And here is a version that requires only one argument. I replaced the missing second parameter error with one where variable is not defined:
Code: Select all
:NormalizeFilespec - <var:Input/Output> -- "normalize + guarantee \ at end of directory path."
:: returns (additional) error(123) if filespec(file/path) is not existing.
IF "%~1" EQU "" >&2 ECHO Err(:NormalizeFilespec): missing parameter.&EXIT /b 96001
IF not defined %~1 >&2 ECHO Err(:NormalizeFilespec): variable not defined - %~1&EXIT /b 96002
SETLOCAL enableDelayedExpansion
set "fpath=!%~1!"
for /f "eol=: delims=" %%a in ("!fpath!") do set "fpath=%%~fa"
if "!fpath:~-1!" neq "\" dir "!fpath!\." >nul 2>nul && set "fpath=!fpath!\"
if not exist "!fpath!" (set "err=123") else (set "err=0")
ENDLOCAL & set "%~1=%fpath%" & EXIT /b %err%
While delayed expansion is enabled, I like to restrict variable expansion to !var! form in case the contents contain ! or ^. Both of these characters can appear in a file name and the characters will not be preserved if you use %var% expansion while delayed expansion is enabled.
In case you really prefer to strip final \ from directory paths, unless root directory:
Code: Select all
:NormalizeFilespec - <var:Input/Output> -- "normalize + strip ending \ unless root"
:: returns (additional) error(123) if filespec(file/path) is not existing.
IF "%~1" EQU "" >&2 ECHO Err(:NormalizeFilespec): missing parameter.&EXIT /b 96001
IF not defined %~1 >&2 ECHO Err(:NormalizeFilespec): variable not defined - %~1&EXIT /b 96002
SETLOCAL enableDelayedExpansion
set "fpath=!%~1!"
for /f "eol=: delims=" %%a in ("!fpath!") do set "fpath=%%~fa"
if "!fpath:~-1!" equ "\" if "!fpath:~-2,1!" neq ":" set "fpath=!fpath:~0,-1!"
if not exist "!fpath!" (set "err=123") else (set "err=0")
ENDLOCAL & set "%~1=%fpath%" & EXIT /b %err%
Dave Benham