I have the following which pares down a folder name (FOLDER) to only all text preceding the first space (tmpFOLDER).
@echo off
setlocal EnableExtensions DisableDelayedExpansion
pushd "%~dp0" || exit /B
for %%I in (..) do set "FOLDER=%%~nxI"
for /f "tokens=1 delims= " %%a in ("%FOLDER%") do set tmpFOLDER=%%a
ECHO %FOLDER%
ECHO %tmpFOLDER%
popd
endlocal
PRIMARY REQUEST:
Is there a way to do this in reverse?
Folder name (%FOLDER%): Smith - John
Example current (%tmpFOLDER%): Smith
Example desired (%tmpFOLDER%): John
SECONDARY:
Is there a way to do this with files, as well, disregarding any filetypes (ie. .txt)?
File name (%FILE%): "Smith - John.txt"
Example current (%tmpFILE%): Smith
Example desired (%tmpFILE%): John
CodePudding user response:
The for /F loop cannot extract tokens counted from the end of a string. However, you could use a standard for loop that walks through the words of the file or directory names:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Retrieve base name of grand-parent directory of this script:
for /D %%I in ("%~dp0..") do set "FOLDER=%%~nI"
echo Old name: "%FOLDER%"
set "PREV=" & set "COLL="
rem /* Unnecessary loop iterating once and returning the whole directory name;
rem it is just here to demonstrate how to handle also more than one names: */
for /F "delims= eol=|" %%L in ("%FOLDER%") do (
rem // Store current name strng and reset some interim variables:
set "NAME=%%L" & set "PREV=" & set "COLL= "
rem // Toggle delayed expansion to avoid issues with `!` and `^`:
setlocal EnableDelayedExpansion
rem // Ensure to have each space-separated word quoted, then loop through them:
for %%K in ("!NAME: =" "!") do (
rem /* Build new buffer by concatenating word from previous loop iteration,
rem then transfer it over `endlocal` barrier (localised environment): */
for %%J in ("!COLL! !PREV!") do (
rem // Store current word in an unquoted manner:
endlocal & set "ITEM=%%~K"
rem // Store current buffer, store current word for next iteration:
set "COLL=%%~J" & set "PREV=%%~K"
setlocal EnableDelayedExpansion
)
)
endlocal
)
rem // Retrieve final result:
set "RESULT=%COLL:~3%"
echo New name: "%RESULT%"
echo Last word: "%PREV%"
endlocal
exit /B
This approach returns the name with the last word removed as well as the last word of the name.
An alternative solution is the sometimes so-called code injection technique, which requires delayed variable expansion and is quite hard to understand:
setlocal EnableDelayedExpansion
echo Old name: "%FOLDER%"
set "RESULT=%FOLDER: =" & set "RESULT=!RESULT!!ITEM!" & set "ITEM= %"
echo New name: "%RESULT%"
echo Last word: "%PREV%"
endlocal
Note, that this will fail when the input string contains !, ^ or " (but the latter cannot occur in file or directory names anyway).
