I am working on and can only work with a batch file. No PowerShell.
I would like to remove the FIRST occurrence of a substring in a string.
@echo off
@setlocal enableextensions enabledelayedexpansion
set "str=C:\help\te\Windows\Example\001 Example\te\005 Example"
echo -----------Original string---------------------------
echo !str!
echo ----------This removes EVERY \te\----------------------------
echo !str:\te\=\!
echo -----------This gets everything after first \te\---------------------------
set "strAfter=!str:*\te\=\!"
echo !strAfter!
echo ----------This gets everything before first \te\----------------------------
echo how?
echo ---------simply get rid of FIRST \te\-----------------------------
echo how?
echo -----------------I could work with the position of the first \te\-------------------------------
echo how?
PAUSE
I've played with what is above. I've played with for
loop, find
, findstr
.
I've also thought of getting the position of the first \te\
and then proceed with extracting the string before and the string after and finally concatenating. No success with anything.
UPDATE 1: With Magoo's trick, I'm able to make it work. Thank you. (Still reading up on double quotes, %%
, &&
and !!
.)
echo:
echo ------ This gets everything before first \te\--------
rem Replace "everything after \te\" with nothing, then remove \te again
set "strBefore=!str:%strAfter%=!"
set "strBefore=!strBefore:\te=!"
echo !strBefore!
echo:
echo ------ First method--------
set "finalstr=!strBefore!!strAfter!"
echo !finalStr!
I'm still curious to getting a position if ever I need it.
echo:
echo ----(Method2)-- I could work with the position of the first \te\--------
echo ------ if I could get the 7 automatically
set /a ind=7
set before=!str:~0,%ind%!
set after=!str:*\te\=\!
set finalstr=!before!!after!
echo !finalstr!
And curious, there is really no easy 1 or 2 line search for FIRST occurrence?
UPDATE 2: While the small testing script above worked, once I brought it back into the actual script, it breaks. Here's the official script.
@ECHO off
@setlocal enabledelayedexpansion
REM find filenames that are links
For /R %%G in (*.lnk) do (
echo:
echo --------------------------------
set originalLink=%%G
echo For this link : !originalLink!
REM find the Target/cible
for /F "tokens=1 delims=" %%a in ('shortcutJS.bat -examine "%%G" ^| find /i "Target:"') do (
set "targetVar=%%a"
)
REM remove word Target: from front (use double quotes in case of spaces)
set "targetVar=!targetVar:Target:=!"
echo Target file is : !targetVar!
rem TODO count how many \te\ to put an if to skip if useless
REM remove or replace the FIRST folder named \te\ from path
set "strAfter=!targetVar:*\te\=\!"
echo strAfter first \te\: !strAfter!
REM Replace "everything after \te\" with nothing, then remove \te again
set "strBefore=!targetVar:%strAfter%=!"
echo strBefore is: !strBefore!
set "strBefore=!strBefore:\te=!"
echo strBefore: !strBefore!
set "targetNew=!strBefore!!strAfter!"
echo targetNew !targetNew!
REM this would remove every \te\... not good if more than one. trying to change with what's above.
set targetNew=!targetVar:\te\=\!
echo:
echo New target : !targetNew!
REM actually push the new Target to the file...
REM editShortcut.vbs "!originalLink!" "!targetNew!"
PAUSE
)
strAfter
works, but not strBefore
. Here is one output:
--------------------------------
For this link : C:\Users\carol\Desktop\tests raccourcis names serveur\renameLinks2\horloge velo.jpg.lnk
Target file is : C:\Users\carol\Desktop\tests raccourcis names serveur\te\horloge velo.jpg
strAfter first \te\: \horloge velo.jpg
strBefore is: targetVar:=
strBefore: targetVar:=
targetNew targetVar:=\horloge velo.jpg
New target : C:\Users\carol\Desktop\tests raccourcis names serveur\horloge velo.jpg
Appuyez sur une touche pour continuer...
This one-liner works here:
@echo off
setlocal EnableDelayedExpansion
set "str=C:\help\te\Windows\Example\001 Example\te\005 Example"
echo Old: "%str%"
set "repl=\" & set "new=%str:\te\=!repl!" & set "repl=\te\" & set "new=!new!%"
echo New: "%new%"
Output:
Old: "C:\help\te\Windows\Example\001 Example\te\005 Example"
New: "C:\help\Windows\Example\001 Example\te\005 Example"
For a further description on the method used, see this answer
You can also get the position of the first (or all) \te\
string using this similar method
EDIT: New method added as response to comment
The method above requires to use %standard%
expansion in order to work. If you want to perform this replacement into a loop (that would require !delayed!
expansion), you have two options:
1- Use a subroutine to perform the replacement
Just define a subroutine that get the string in the parameter, perform the replacement and returns the result in a variable, and call it from inside the loop:
:replaceFirst
set "str=%~1"
set "repl=\" & set "new=%str:\te\=!repl!" & set "repl=\te\" & set "new=!new!%"
exit /B
2- Replace the delimiter substring by a new-line character, and process the parts in a standard for /F
command:
set "new="
for /F "delims=" %%a in (^"!str:\te\^=^
%Don't remove this line%
!^") do (
if not defined new (
set "new=%%a\"
) else (
set "new=!new!%%a\te\"
)
)
set "new=!new:~0,-4!"
Below is the complete code that solve your problem:
@echo off
setlocal EnableDelayedExpansion
REM find filenames that are links
For /R %%G in (*.lnk) do (
echo:
echo --------------------------------
set originalLink=%%G
echo For this link : !originalLink!
REM find the Target/cible
for /F "tokens=1 delims=" %%a in ('shortcutJS.bat -examine "%%G" ^| find /i "Target:"') do (
set "targetVar=%%a"
)
REM remove word Target: from front (use double quotes in case of spaces^)
set "targetVar=!targetVar:Target:=!"
echo Target file is : !targetVar!
rem TODO count how many \te\ to put an if to skip if useless
REM remove or replace the FIRST folder named \te\ from path
set "targetNew="
for /F "delims=" %%a in (^"!targetVar:\te\^=^
%Don't remove this line%
!^") do (
if not defined targetNew (
set "targetNew=%%a\"
) else (
set "targetNew=!targetNew!%%a\te\"
)
)
set "targetNew=!targetNew:~0,-4!"
echo:
echo New target : !targetNew!
REM actually push the new Target to the file...
REM editShortcut.vbs "!originalLink!" "!targetNew!"
PAUSE
)
EDIT #2: Simpler method added
The following code is a much simpler solution:
REM remove or replace the FIRST folder named \te\ from path
for %%a in ("!targetVar:*\te\=!") do set "targetNew=!targetVar:\te\%%~a=!\%%~a"
echo:
echo New target : !targetNew!