Batch file - can not read a variable - batch-file

Making batch which generate previews (everything is fine with this part of code) and also rename files deleting everything after "_" in filename. For example ABAB_abab.png > ABAB.png
My code does not see a variable yy in the string: set zz=!xx:yy=! Perceives it like just two letters yy, not a variable. How to fix that?
Here is the script
setlocal enabledelayedexpansion
for %%a in ("*.png") do (
set xx=%%~na
set yy=_!xx:*_=!
set zz=!xx:yy=!
echo xx= !xx! #rem (okay, returns ABAB_abab)
echo yy= !yy! #rem (okay, returns _abab)
echo zz= !zz! #rem (wrong, returns ABAB_abab without any substitutions)
pause
)
endlocal
Thank you for help

Here's a quick example to show you a method of achieving another layer of expansion:
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
For %%G In ("*.png") Do (
Set "xx=%%~nG"
SetLocal EnableDelayedExpansion
Set "yy=_!xx:*_=!"
For %%H In ("!yy!") Do Set "zz=!xx:%%~H=!"
Echo xx = "!xx!"
Echo yy = "!yy!"
Echo zz = "!zz!"
EndLocal
Pause
)
The doublequotes are included in the Echo commands only for better visualization should there be any spaces in your strings, they're not needed for any other purpose.
Please note, that this will not achieve your intention with any .png files whose basename begins with one or more underscores, _.

Related

loop over an array in a bat script [duplicate]

This question already has answers here:
Arrays, linked lists and other data structures in cmd.exe (batch) script
(11 answers)
Closed 2 years ago.
I'm new to bat scripting and I wanted to use an iterative loop in my script (something like this in javascript for example)
for(var i=0;i<n;i++){
//my code here
console.log("my tab ["+i+"] is:"+tab[i];
}
So, basicaly this is my bat script in a file called exctract_excel_info.bat:
#ECHO OFF
::setlocal enabledelayedexpansion
:start
ECHO "Hi it's MIBE in this script i will list all the files with the extention xlsx or xls">log.txt
:start_loop
echo Listing all files in the current directory %cd% >log.txt
ECHO ================== ======================>>log.txt
set "AllowExt= *.xls"
ECHO the variable AllowExt in the first instruction %AllowExt%>>log.txt
set theFileName="NONE"
set /a i = 0
for %%a in (%AllowExt%) do (
set /a i = i + 1
::echo Found the file: "%%a">>log.txt
set theFileName[%i%]=%%a
)
:end_loop
ECHO ============================================>>log.txt
ECHO "The value of i is %i%">>log.txt
ECHO ============================================>>log.txt
for /L %%x in (1,1,%i%) do (
ECHO found the file %theFileName[%%x]%>>log.txt
)
ECHO ============================================>>log.txt
timeout /t 2
ECHO Yo the file %theFileName[0]% will be passed as a parameter
ECHO The array of files %theFileName%>>log.txt
:run_node
node main.js "%theFileName[0]%">>log.txt
timeout /t 2
:end
::PAUSE
I have a problem reading the value of the variable theFileName[i] in line 32
ECHO found the file %theFileName[%%x]%>>log.txt
This is the output (log.txt):
Listing all files in the current directory C:\Users\mibe\my bat
================== ======================
the variable AllowExt in the first instruction *.xls
============================================
"The value of i is 4"
============================================
So my problem is what is the proper way to read the value of the items inside theFileName array?
PS: when I comment the lines 31, 32, and 33:
for /L %%it in (1,1,"%i%") do (
ECHO found the file %theFileName[%%it]%>>log.txt
)
the script executes properly and get the value of %theFileName[0]%
The following is a basic example of what I think you're trying to do, up to a point.
The problem is that because you've not told us what exactly you're intending to do with those similarly named variables, I cannot include the specific methodology for doing so. I have therefore just output the defined variable names along side their value strings.
#SetLocal EnableExtensions DisableDelayedExpansion
#For /F "Delims==" %%G In ('"(Set File[) 2> NUL"') Do #Set "%%G="
#Set "i=0" & For /F Delims^= %%G In (
'"(Set PATHEXT=) & "%__APPDIR__%where.exe" ".:*.xlsx" ".:*.xls" ".:*.csv" 2> NUL | "%__AppDir__%sort.exe""'
) Do #(Set /A i += 1 & SetLocal EnableDelayedExpansion
For %%H In (!i!) Do #EndLocal & Set "File[%%H]=%%~nxG")
#If Defined File[1] For /L %%G In (1,1,%i%) Do #(SetLocal EnableDelayedExpansion
Echo File[%%G]=!File[%%G]! & EndLocal)
#Pause
The code above should define individual variables, each containing the string value of a file in the current directory, which has an extension of either .xlsx, .xls, or .csv.
When I first looked at your question I initially thought that you were intending to pass each file name together as multiple arguments to your node command.
If that is what you're actually intending to do, then I'd assume the following example would suit your purposes better.
#SetLocal EnableExtensions DisableDelayedExpansion
#Set "FileList="&For /F Delims^= %%G In (
'"(Set PATHEXT=) & "%__APPDIR__%where.exe" ".:*.xlsx" ".:*.xls" ".:*.csv" 2> NUL | "%__AppDir__%sort.exe""'
) Do #If Not Defined FileList (Set "FileList="%%~nxG"") Else (SetLocal EnableDelayedExpansion
For /F Delims^=^ EOL^= %%H In ("!FileList!") Do #EndLocal & Set "FileList=%%H "%%~nxG"")
#If Defined FileList Echo %%FileList%%=%FileList%
#Pause
The code above should define a single variable, containing the space separated, and doublequoted, string values, of each file in the current directory, which has an extension of either .xlsx, .xls, or .csv.
Please note that there is a command line length limitation so be aware that your value could become truncated.
In both examples:
The last line, #Pause, is included only to prevent premature closure of the cmd window, should you not be testing this from the CLI. (You can safely remove it if you are).
I assumed you wanted only the filenames without their paths, in the variable values. Should you wish for the full paths, just change %%~nxG in your chosen example code to %%G.
BTW, I used sort.exe against the returned files, because you mentioned array, and IMO an array should be ordered. (If you do not need that functionality, you could remove | "%__AppDir__%sort.exe" from your chosen example code).
Please note that there is a limit to the size of the environment, so be aware that if you have many matching files, they have long filenames, include paths etc. you may reach or exceed that limitation.
Having provided some examples for you, I'm not sure why you could not just iterate your directory, and create an array of those files, directly using .js, (off topic).

Batch Recursive For Loop and non-ASCII characters in Folder Namers

This is my continuing attempt to build a filename format verification batch routine (batch variable exclamation points used in dir | findstr)
Here's where I'm at:
echo off
REM Ensure filenames are of the format ALBUM - TITLE
chcp 1254>nul
setlocal DisableDelayedExpansion
set /p CUTOFFDATE=Enter the Date of the Last Cleanup (yyyymmdd):
for /r "\\kodi-pc\g\itunes\iTunes Media\Podcasts\American Civil War\" %%i in (*.mp3) do (
set "FILENAME=%%~nxi"
set "FILEDATE=%%~ti"
call set "TITLE=%%FILENAME:* - = - %%"
call:SETALBUM
call set "FILEDATE=%%FILEDATE:~6,4%%%%FILEDATE:~0,2%%%%FILEDATE:~3,2%%"
setlocal EnableDelayedExpansion
if !FILEDATE! GTR !CUTOFFDATE! (
echo ~ALBUM~TITLE~FILENAME~ ~!ALBUM!~!TITLE!~!FILENAME!
)
endlocal
)
pause
exit /b
:SETALBUM
call set "ALBUM=%%FILENAME:%TITLE%=%%"
exit /b
Works great except where folder names contain non-ASCII characters (», ’, etc.). My effort has been to recognize bangs (!) but that accomplished I now have these other problems.
The foldername 'American Civil War' is merely a sample placeholder for this forum. In reality I loop through many hundreds of foldernames.
Thx.

Looking for a script to rename multiple files with charactares already in filename

I have many files in many folders that I need to rename.
And example is
from cgs2016-09-05-05-40-34.xls
to cgs0905.xls
and
from cgs2016-09-06-05-40-34
to cgs0906.xls
etc
Any help would be greatly appreciated!
#Jamaz Try out the following code below on a sample of your files. Again please use it on a test sample of your files so it does not cause you issues if it makes a mistake. Thank you and please up-vote if this works for you.
setlocal enabledelayedexpansion
REM Collect list of file names in current directory that have the .xls file extension. Output to text file.
dir /b "*.xls" >xls.txt
REM For loop examines the text file for individual file names.
FOR /F "tokens=1" %%# in (.\xls.txt) do (
REM SET variable "#" to equal "token"
Set "token=%%#"
REM Extract the first 3 characters (year) from the file name and set is to variable "token"
Set "tokenchar=!token:~0,3!"
REM Extract the month characters from the file name and set the variable as "tokenmonth"
Set "tokenmonth=!token:~8,2!"
REM Extract the day characters from the file name and set the variable as "tokenday"
Set "tokenday=!token:~11,2!"
ren "%%#" "!tokenchar!!tokenmonth!!tokenday!.xls"
echo %%#
)
Pause
not the best way, but works for your examples:
#echo off
setlocal enabledelayedexpansion
for %%x in (*.xls) do (
set "filename=%%x"
ECHO ren "%%x" "!filename:~0,3!!filename:~8,2!!filename:~11,2!.xls"
)
remove the ECHO if output is ok.
Because the last nineteen characters, date and time stamp, are more likely to be constant than the first three, (especially over multiple folders), I'd change both the previous answers to cater for that rationale.
#Echo Off
SetLocal EnableDelayedExpansion
(Set _rf=C:\Users\jamaz\TestDir)
(Set _fe=xls)
If Not Exist "%_rf%\" Exit/B
For /R "%_rf%" %%I In (*.%_fe%) Do (Set "_fn=%%~nI"
Echo=Ren "%%I" "!_fn:~,-19!!_fn:~-14,2!!_fn:~-11,2!%%~xI")
Timeout -1 1>Nul
EndLocal
Exit/B
As the OP was not clear about whether the code was for multiple same level folders or subfolders rooted from a single location, I went for the latter as the previous responses had already covered that.
Change your chosen file path and extension on lines 4 and 5
If you are happy with the console output, remove echo= from line 10 and delete line 11

batch %var:*\% to eliminate all before last \ not first

set var=C:\Users\user\Desktop\bla\bla.exe
set var=%var:*\%
echo %var%
this returns Users\user\Desktop\bla\bla.exe - is there any way to make it focus on the last \ and not the first one so that it would just return bla.exe? bear in mind that this will be used on multiple files and folders so i won't always know how many sub-folders there are.
#ECHO OFF
SETLOCAL
set "var=C:\Users\user\Desktop\blah blah\bla.exe"
FOR %%a IN ("%var%") DO (
SET "filename=%%~nxa"
FOR %%b in ("%%~dpa.") DO SET "lastleaf=%%~nxb"
)
ECHO filename is "%filename%"
ECHO lastleaf is "%lastleaf%"
GOTO :EOF
Normally, the next question is about how to obtain the last leaf of the directory-tree. No subroutines required...
Note positioning of quotes to minimise problems with separators. ALso minor directory name-change to exhibit differences.
The following snippet shows one way to do it.
#setlocal enableextensions enabledelayedexpansion
#echo off
:main
set var=C:\Users\user\Desktop\blah blah\yada yada.exe
call :basename result "%var%"
echo %result%
endlocal
goto :eof
:basename
set %1=%~nx2
goto :eof
It basically calls a function basename (named after the UNIX utility), passing the full name and the variable you want to assign the base name to, and you need to make sure you quote it properly lest filenames containing spaces will cause you problems.
The full set of variable modifiers can be seen in the call /? help output.
Alternatively, you can use the same basename functionality in a one-liner for statement:
for /f "delims=" %%I in ("%var%") do set result=%%~nxI
This allows you to get the base name without having to call a function. I tend to prefer the function myself since it's more readable but you could probably alleviate that by just including a comment:
rem Get base name of var into result:
rem eg: var = C:\Users\user\Desktop\blah blah\yada yada.exe
rem result = yada yada.exe
for /f "delims=" %%I in ("%var%") do set result=%%~nxI

How to change an image tag url in multiple html files using batch script?

There are more than 10 html files with image tags. Every time we deploy our build onto test site we need to change the img source. for eg <img src=/live/Content/xyz.png />
to <img src=/test/Content/xyz.png />.
After looking around and reading for sometime, i have come up with the following batch script, however i cant figure out how do i go further from here :
for /r %%i in (*.html) do echo %%i
for %%f in (*.html) do (
FOR /F %%L IN (%%f) DO (
SET "line=%%L"
SETLOCAL ENABLEDELAYEDEXPANSION
SET "x= <--------------------WHAT DO I SET HERE?
echo %x%
ENDLOCAL )) pause
This is my first batch script, could anyone please guide me in the right direction?
#ECHO OFF
SETLOCAL enabledelayedexpansion
for /r U:\ %%i in (*.html) do (
echo found %%i
SET outfile="%%~dpni.lmth"
(
SETLOCAL disabledelayedexpansion
FOR /F "usebackq delims=" %%L IN ("%%i") DO (
SET "line=%%L"
SETLOCAL ENABLEDELAYEDEXPANSION
SET "line=!line:/live/=/test/!
echo !line!
ENDLOCAL
)
ENDLOCAL
)>!outfile!
)
pause
GOTO :EOF
How about this development?
Notes:
I've modified your FOR/R to ECHO the HTML file being processed and use %%i rather than switching to %%f. U: is my RAMDRIVE; you'd need to modify that to suit.
outfile is set to generate a filename which matches the HTML filename, but with a .lmth extension (can't update in-place) - it gets that from the ~dpn prefixing the i, which means the drive, path and name of the file %%i. It's quoted to take care of potential spaces in the filename or pathname.
The next logical statement is (for /f...[lines] )>!outfile! which sends any echoed text to a NEW file !outfile!. The enabledelayedexpansion in the second physical line of the batch makes !outfile! the RUN-TIME value - as it is changed within the FOR r outer loop.
Since the actual HTML filename in %%i may contain spaces, it needs to be quoted, hence the 'usebackq' clause in the FOR/F. The delims= clause ensures that the ENTIRE line from the file "%%i" is applied to %%L - not just the first token (well, actually, makes the entire line the first token).
The SET command substitutes the string "/test/" for any occurrence of "/live/" in the RUN-TIME value of the variable lineand assigns the result to line. The resultant value is then ECHOd - which is redirected to outfile
Note that in your original, you would be assigning x in the set x= but echo %x% would have reproduced x as it stood when the line was PARSED because batch substitutes the value of any variable for %var% as part of the parsing phase. Consequently, the line would have become simply ECHO (since x would likely be unassigned) and bizarrely would have reported the echo state (Echo is OFF)
A couple of gatchas here. First, % and some other characters are notoriously hard to process with batch, so be careful. Next, FOR/F will bypass empty lines. This can be overcome if required. Third, this will replace ANY occurrence of /live/ in any case with /test/
Good luck!
Edit to support exclamation marks: 20130711T0624Z
Added SETLOCAL enabledelayedexpansion line and ENDLOCAL just before )>!outfile! to match

Resources