Batch For file loop String Replacement - windows

I have a few mp4 file in a directory, which was named by wget, an utility used to download files from the internet.
The thing is, it wrote filename as "1%20-%201%20-%20Overview%20%2802%3A09%29.mp4"(percent encoding of string "1 - 1 - Overview (02:09)"), which is a nuisance - it's not that straightforward. So I decided to use batch command to convert them.
As those files only contain a few special letters(space, colon and brackets), I thought I'd just execute a few commands in cmd, and after trying a few commands intended to change %20 to SPACE, I'm stuck.
In batch files, I'd use:
#echo off
setlocal enabledelayedexpansion
for %%i in (*.mp4) do (
set aaa=%%i
rename "%%i" "!aaa:%%20= !"
)
and I've tried (for testing):
SETLOCAL enabledelayedexpansion
FOR %i in (*.mp4) do (
SET aaa="%i"
echo "!aaa:%%20= !"
)
I tried changing '!' to '%', but it didn't work. It seems that it rather prints exactly what I wrote(like a few lines of !aaa:%%20= !), or the value of aaa doesn't change.
Can somebody help me? I thought just changing '%%' to '%' would convert a batch file script to cmd commands. What are other differences, if not?

#echo off
setlocal
:: Define simple macros to support JavaScript within batch
set "beginJS=mshta "javascript:close(new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1).Write("
set "endJS=));""
SETLOCAL enabledelayedexpansion
FOR %%i in (*.mp4) do (
for /f %%N in (
'%beginJS% decodeURIComponent("%%i") %endJS%'
) do set "dec=%%N"
echo !dec!
)
What if you try decodeURIComponent from javascript (with mshta) ?

Your problem is SETLOCAL does not work from the command line, so you never activate delayed expansion.
Also, you should put the quote before the variable being assigned so the quotes are not included in the value.
You can start a new cmd.exe shell with delayed expansion enabled to make things work.
cmd /v:on
FOR %i in (*.mp4) do (SET "aaa=%i"&echo "!aaa:%%20= !")
You need to be aware that you cannot change %3A to : because : is not valid in file names.
You might want to look into my JREN.BAT utility that uses regular expression search and replace to rename files:
You could do something like:
jren "%20" " " /fm *.mp4
jren "%3A" "." /fm *.mp4
You would need to precede each command with CALL and double the percents if you use the above in a batch script.
Note that I converted %3A to . instead of : because the colon cannot be used in a file name.

Related

Replace Backslash with Forwardslash in Windows batch script

I am writing a simple batch script to get the filenames in a folder and write the output to a file. At the same time, I am appending a string to the file.
#echo off
set $string=!source ./
set "loc=C:\path\to\dir\files\scripts\"
pushd %loc%
(for %%a in (*) do (
echo %$string%%%~dpnxa))>output.txt
popd
output.txt:
!source ./C:\path\to\dir\files\scripts\abc.txt
!source ./C:\path\to\dir\files\scripts\xyz.txt
I am having a hard time replacing backslash \ with forward-slash / in the output and also removing this part C:\path\to\dir\files\ from the path.
In the end, I am trying to achieve something like this written to a file:
final_output.txt:
!source ./scripts/abc.txt
!source ./scripts/xyz.txt
Any help will be great.
#ECHO Off
SETLOCAL
set "$string=!source ./"
set "loc=U:\path\to\dir\files\scripts\"
pushd %loc%
FOR %%a IN ("%loc%.") DO SET "locparent=%%~dpa"
(for %%a in (*) do (
SET "line=%%~dpnxa"
CALL SET "line=%$string%%%line:%locparent%=%%"
CALL ECHO %%line:\=/%%))>output.txt
popd
GOTO :EOF
[I used drive u: for testing]
Yo can't substring a metavariable (%%a in this case) - you need to transfer to a uservariable.
Having established line, use call set to execute the command SET "line=valueof$string%line:valueofloc=%", which replaces the unrequired string already in line by nothing.
Then use call echo to execute ECHO %line:\=/%, replacing any remaining \ with /.
Your narrative states you wish to remove C:\path\to\dir\files\scripts from the output, but your example output includes scripts.
[adjusted include the leafname]

cmd - Remove last \ from the searched folder

I need folder's full path given it has .txt file
Currently I am using the following command
D:\Testfolder\_dn>for /r %i in (*.txt) do #echo %~dpi
And getting the following output
D:\Testfolder\_dn\2nd\
D:\Testfolder\_dn\3rd\
D:\Testfolder\_dn\4th\
D:\Testfolder\_dn\5th\
D:\Testfolder\_dn\first\
But I want the output like following
D:\Testfolder\_dn\2nd
D:\Testfolder\_dn\3rd
D:\Testfolder\_dn\4th
D:\Testfolder\_dn\5th
D:\Testfolder\_dn\first
I tried remove last characters string batch
for /r %i in (*.txt) do #echo %~dpi:~0,-1%
But it is not working.
How can I remove the last \ from the search result?
The sub-string expansion syntax works on normal environment variables only, but not on for variable references. To apply that syntax you need to assign the value to a variable first:
for /R %i in ("*.txt") do #(set "VAR=%~dpi" & echo/!VAR:~^,-1!)
But since you are editing a variable value within a block of code (loop), you need to enable and to apply delayed variable expansion. This can be established by opening the command line instance by cmd /V:ON or cmd /V. However, this can still cause trouble when a path contains !-symbols.
An alternative and better solution is to avoid string manipulation and delayed variable expansion by appending . to the paths (meaning the current directory) and using another for loop to resolve the paths by the ~f modifier of the variable reference, like this:
for /R %i in ("*.txt") do #for %j in ("%~dpi.") do #echo/%~fj
The "" avoid problems with paths containing SPACEs or other token separators (,, ;, =,...).
Be sure to enable delayed expansion so that the P variable gets reevaluated in the loop.
SETLOCAL ENABLEDELAYEDEXPANSION
for /r %%i in (*.txt) do (
SET "P=%%~dpi"
echo !P:~0,-1!
)

String replacement within FOR /F into batch file

There are a handful of questions on SO that look similar, but I cannot figure out some behaviour and I am looking for help.
Below is a snippet from a batch file I am trying to write which will load in a set of directories and potentially replace letter substitutions with an expanded path, e.g. the properties file might look like:
location1=C:\Test
location2=[m]\Test
Where location1 points to C:\Test and location2 points to C:\Program Files(x86)\MODULE\Test, because [m] is a shorthand to C:\Program Files(x86)\MODULE.
The batch script, to this point, is simply trying to read in the list of file paths and expand/replace the [m].
SET build.dir=%~dp0%
SET progfiles=%PROGRAMFILES(X86)%
IF "%progfiles%"=="" SET progfiles=%ProgramFiles%
SET local.properties=%build.dir%local.properties
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /F "tokens=1* delims==" %%i IN (%local.properties%) DO (
SET local.dir=%%j
SET local.dir=!local.dir:[m]=%progfiles%\MODULE!
echo !local.dir!
)
ENDLOCAL
Running this kicks out an error:
\MODULE was unexpected at this time.
If I replace the FOR with the following instead:
set test="[m]\Proj\Dir"
set test=!test:[m]=%progfiles%\MODULE!
echo %test%
I get the desired C:\Program Files(x86)\MODULE\Proj\Dir printed out...so I'm confused why it works fine outside of the FOR loop.
My understanding about delayed expansion is that it 'expands' at runtime...which you get to happen using !! instead of %% wrapped around the variable. Furthermore, as I'm creating the local.dir variable inside the FOR loop scope, I must use delayed expansion in order to access it with the updated value for the iteration.
I feel like the problem is using %progfiles%, like there's some special syntax I need to use in order to make it work but nothing is adding up for me. When I echo %progfiles%, it prints out as C:\Program Files(x86 -- note the missing trailing ).
Any ideas? Thanks
Tested suggestion:
D:\Projects\Test\Build>test
*** "D:\Projects\Test\Build\local.properties"
*** "","C:\Program Files (x86)"
[m]=C:\Program Files (x86)\MODULE
Adding quotes around the whole expression makes it work -- can't use other characters for some reason (like []) -- and since I want to append to the path later, we can safely remove the quotes afterwards:
SET local.dir="!local.dir:[m]=%progfiles%\MODULE!"
SET local.dir=!local.dir:"=!
Test this to see if you can nut out the issue:
The double quotes are to provide robust handling in a system with long file/path names.
The () are unquoted which are a problem in a batch script, when inside a loop.
#echo off
SET "build.dir=%~dp0%"
SET "progfiles=%PROGRAMFILES(X86)%"
IF "%progfiles%"=="" "SET progfiles=%ProgramFiles%"
SET "local.properties=%build.dir%local.properties"
echo *** "%local.properties%"
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /F "usebackq tokens=1* delims==" %%i IN ("%local.properties%") DO (
SET "local.dir=%%j"
echo *** "!local.dir!","%progfiles%"
SET "local.dir=!local.dir:[m]=%progfiles%\MODULE!"
echo !local.dir!
)
ENDLOCAL
pause
It has to do with the () characters that end up in your progfiles string. If you take them out, the substitution seems to work fine.
My suggestion is to ditch command for this particular purpose and use one of the other standard tools that Windows comes with. While my personal preference would be Powershell (since it's so much more powerful and expressive), you may just need something quick that you can integrate into existing cmd.exe stuff.
In that case, try the following VBScript file, xlat.vbs:
set arg = wscript.arguments
wscript.echo Replace(arg(0),arg(1),arg(2))
Your batch file then becomes something like, noting the inner for /f which captures the output of the VBS script and assigns it to the variable:
#echo off
SET build.dir=%~dp0%
set progfiles=%PROGRAMFILES(X86)%
if "%progfiles%"=="" set progfiles=%ProgramFiles%
set local.properties=%build.dir%local.properties
setlocal enabledelayedexpansion
for /f "tokens=1* delims==" %%i in (%local.properties%) do (
set local.dir=%%j
for /f "delims=" %%x in ('cscript.exe //nologo xlat.vbs "!local.dir!" "[m]" "%progfiles%\MODULE"') do set local.dir=%%x
echo !local.dir!
)
endlocal
Running that, I get the output:
C:\Test
C:\Program Files (x86)\MODULE\Test
which I think is what you were after.

Want to rename a file through windows batch file scripting

Here is my file MY_APP_CON_123_yyyymmdd.hhmmss.txt where "yyyymmdd.hhmmss" is variable data. I want to rename it to MY_APP_CON_0123_yyyymmdd.hhmmss.txt (Zero infront of 123). When I use ren command as shown below, the first y disappears from the file name.
REN MY_APP_CON_123_* MY_APP_CON_0123_*
Any solutions ?
Not answer, but explaining why your rename isn't working:
cmd.exe/command.com's wildcard renaming is position based, e.g.
filename: abc123.txt
command: ren abc*.txt abd1*.txt
will do:
abc123.txt - original name
||||**.txt
abd1**.txt - rename pattern
----------
abcd23.txt - new filename
https://superuser.com/questions/475874/how-does-the-windows-rename-command-interpret-wildcards
Wildcard renaming where you want to change parts of the filename and the new part has a different length from the original part gets very hairy.
Here is a pure batch solution.
#echo off
for %%F in (MY_APP_CON_123_*) do #set "name=%%F"&call ren "%%name%%" "%%name:*MY_APP_CON_=MY_APP_CON_0%%"
Or, with delayed expansion:
#echo off
setlocal enableDelayedExpansion
for %%F in (MY_APP_CON_123_*) do #set "name=%%F"&ren "!name!" "!name:*MY_APP_CON_=MY_APP_CON_0!"
But I would use my JREN.BAT regular expression renaming utility - a hybrid JScript/batch script that runs natively on any Windows machine from XP onward.
call jren "^MY_APP_CON_123_" "MY_APP_CON_0123_" /i /fm *.txt
for %%a in (MY_APP_CON_123_**) do set "name=%%a" & ren %name% %name:123=0123%
This worked for me

DOS Batch: Getting partial file names

I've got this little batch file I'm trying to write for a Windows 7 environment. It's supposed to go through a directory and echo the last four characters of the file names. So far I've got:
#ECHO OFF
SETLOCAL
for /r C:\Users\userName\Desktop\testFolder %%g in (*) do (
Set fileName = %%~ng
echo %fileName:~-4%
)
And all that is echoed out is "~-4" once for each file in testFolder. I can't figure out what's wrong, but then I'm not very well versed in batch files or dos. Any help would be appreciated, thanks.
Environment variable expansion occurs when the command is read, so your %fileName:~-4% is evaulated when the for is read, which is before the Set is performed. Use delayed expansion.
#ECHO OFF
SETLOCAL SETDELAYEDEXPANSION
for /r C:\Users\userName\Desktop\testFolder %%g in (*) do (
Set fileName=%%~ng
echo !fileName:~-4!
)
Note also that spaces are significant in the Set command. With the space, you created a variable called fileName  with a trailing space.

Resources