I have a string containing filename like below batch script lines:
set "file1=name.php_2017_23_08_12_22_07"
set "file2=name.vbs_2016_16_12_12_13_03"
....
Now as you see above, the list of filenames and their extensions is variety and I need to get the real filenames with their actual extensions (.php, .vbs) respectively. So when I pass in a function with filename with extension I should get actual filenames like below:
call :restoreFile %file2% ".vbs"
should give me output, removing everything after .vbs in the variable %file2%:
name.vbs
And so on for other variables too.
How can set a function like that, which strips a dynamic substring from filename string ?
I tried the below code, but that doesn't work with dynamic substring or text, which can be substitued from variable:
set targetfile=%file2:.vbs=&rem.%
No need to specify the extension - it's still in the name.
Use a for /f to split at the first underscore.
:restoreFile
Set "FileName="
For /f "tokens=1* delims=_" %%N in ("%~1") Do Set "FileName=%%N"
If defined FileName Echo Ren %1 %FileName%
Goto :Eof
You may even put the date_time in front of the extension and so avoid possible dupes:
:restoreFile
Set "FileName="
For /f "tokens=1* delims=_" %%N in ("%~1") Do Set "FileName=%%~nN_%%M%%~xN"
If defined FileName Echo Ren %1 %FileName%
Goto :Eof
The ren commands are prepended with an echo, if the output looks OK remove the echo.
Related
In windows 10, I need to make a batch with a loop on the subfolder names in a folder, I did the following, but the problem is the %%I doesn't manage the folder name with spaces, it takes only the first part:
#echo off
FOR /F %%I IN ('dir /b C:\Users\Thomas\Music') DO (
ECHO %%I)
If the folder "Music" contains the folder "My music", then echo %%I will print only "My".
FOR /F "delims=" %%I IN ('dir /b /ad C:\Users\Thomas\Music') DO (
... and use "%%I" where you want to use the name-containing-spaces (ie. quote the constructed string) - a principle that applies wherever batch uses strings containing separators like Space
The /ad selects directorynames instead of filenames.
Adding a further switch, /s will scan the entire subdirectory-tree.
Assignment of string values to variables is best done with
set "var=%variablefrom%"
or in the case of a metavariable (eg the loop-control variable %%I in your code) you need
set "var=%%I"
BUT you should investigate the topic of delayed expansion (many items here) if you want to use the value of the variable assigned (var) within the loop.
My best-practice concept shown in a commented .bat script:
#ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
FOR /F "delims=" %%I IN ('dir /b /AD "%UserProfile%\Music" 2^>NUL') DO (
rem process a FOR-loop variable directly
ECHO For_variable "%%~I"
rem set a FOR-loop variable as an environment variable value
set "_myVar=%%~I" see tilde which would strip double quotes
rem process an environment variable INside a FOR-loop body
SETLOCAL EnableDelayedExpansion
echo Env_variable "!_myVar!"
ENDLOCAL
rem process an environment variable OUTside a FOR-loop body
call :ProcessMyVar
)
ENDLOCAL
goto :eof
:ProcessMyVar
rem process an environment variable OUTside a FOR-loop body
echo Env_var_Call "%_myVar%"
goto :eof
Output shows that even names with cmd-poisonous characters like percent or exclamation (etc. etc.) are processed properly:
==> tree "%UserProfile%\Music"
Folder PATH listing
Volume serial number is 0000005F F2DF:F89D
C:\USERS\USER\MUSIC
├───100% My Tunes!
└───My Songs!
==> D:\bat\SO\39697872.bat
For_variable "100% My Tunes!"
Env_variable "100% My Tunes!"
Env_var_Call "100% My Tunes!"
For_variable "My Songs!"
Env_variable "My Songs!"
Env_var_Call "My Songs!"
==>
Resources (required reading, incomplete):
(command reference) An A-Z Index of the Windows CMD command line
(helpful particularities) Windows CMD Shell Command Line Syntax
(%I, %~I etc. special page) Command Line arguments (Parameters)
(special page) EnableDelayedExpansion
(>, & etc. special page) Redirection
(%% doubled percent sign, ^ caret, double quotes) Escape Characters, Delimiters and Quotes
How do you trim the date from a text file. For example, I have multiple files like:
test_MX_abc_20091011.txt
test_MX_pqrdhdsu_20091011.txt
test_MX_xyieuz_20091011.txt
All files will have test_MX in common but the 3rd part will of different size.
I would like to change into:
test_MX_abc.txt
test_MX_pqrdhdsu.txt
test_MX_xyieuz.txt
I know how to change the file if name is like test_20091011.txt with the below code, But if name has more string along with date, how to do that?
for /F "tokens=1 delims=_" %%i in ("%%~na") do (
move /Y %%~fa %data_in%\%%i%%~xa >nul
)
Thanks in advance.
This rename operation can be done for example with:
#echo off
for /F "tokens=1-3* delims=_" %%A in ('dir /A-D /B test_MX_*.txt') do (
ren "%%A_%%B_%%C_%%D" "%%A_%%B_%%C.txt"
)
Each file name is separated into 4 strings assigned to loop variables A to D with using underscore as separator. The loop variable D takes everything of file name after third underscore.
Or also working for the 3 files:
#echo off
setlocal EnableDelayedExpansion
for /F "delims=" %%F in ('dir /A-D /B test_MX_*.txt') do (
set "ActFileName=%%~nF"
set "NewFileName=!ActFileName:~0,-9!"
ren "%%~F" "!NewFileName!.txt"
)
endlocal
This solution assigns the name of a file without file extension and path to environment variable ActFileName. Next a new environment variable with name NewFileName is defined with name of active file without the last 9 characters (underscore and date string). This modified file name is used next in the rename operation.
Other solutions using commands for, set and ren can be found on Stack Overflow.
Search with the string
[batch-file] for set rename files
and more than 600 results are presented all using more or less something like above.
For details on the used commands, open a command prompt window, execute one after the other following commands and read output help.
dir /?
for /?
ren /?
set /?
I need to remove a string that may occur inside a file. The string has many lines. Can I perform this action using a Batch script?
I've heard that you cant have variables with more than one line in Batch? The string will come from another file that I will read into a variable using Batch.
The following code seems to only store the 1st/last line of a file in the string?? Whats going wrong?
Rem Read file and store all contents in string
Set replace=
Set target=
Set OUTFILE=res.txt
for /f "delims=" %%i in (myFile.txt) do set target=%target% %%i
echo %target%
Rem When I print target I only have one line not many lines?? Whats going wrong
Rem Remove the target string from myOtherFile.txt: this code is from http://stackoverflow.com/questions/5273937/how-to-replace-substrings-in-windows-batch-file
for /f "tokens=1,* delims=¶" %%A in ( '"type myOtherFile.txt"') do (
SET string=%%A
SET modified=!string:%target%=%replace%!
echo !modified! >> %OUTFILE%
)
Try this:
#echo off &setlocal enabledelayedexpansion
for /f "delims=" %%i in (myFile.txt) do set "target=!target! %%i"
echo %target%
Inside a code block you need always delayed expansion for variables with variable values.
Try this, change last to:
echo !target!
I have a requirement where i'd like to read values from a .properties file
my properties file test.properties content
file=jaguar8
extension=txt
path=c:\Program Files\AC
From the above file I need to fetch jaguar or anything after =
Please help me. Thanks
For /F "tokens=1* delims==" %%A IN (test.properties) DO (
IF "%%A"=="file" set file=%%B
)
echo "%file%"
hope this could help
#echo off
FOR /F "tokens=1,2 delims==" %%G IN (test.properties) DO (set %%G=%%H)
echo %file%
echo %extension%
echo %path%
Note that there is no space after %%H. Else this causes a space to be appended, to file paths for example, and will cause file not found errors when the variables from the property files are used as part of a file path.Struggled for hours because of this!
A solution with support for comments (# style). See comments in code for explanation.
test.properties:
# some comment with = char, empty line below
#invalid.property=1
some.property=2
some.property=3
# not sure if this is supported by .properties syntax
text=asd=f
properties-read.bat:
#echo off
rem eol stops comments from being parsed
rem otherwise split lines at the = char into two tokens
for /F "eol=# delims== tokens=1,*" %%a in (test.properties) do (
rem proper lines have both a and b set
rem if okay, assign property to some kind of namespace
rem so some.property becomes test.some.property in batch-land
if NOT "%%a"=="" if NOT "%%b"=="" set test.%%a=%%b
)
rem debug namespace test.
set test.
rem do something useful with your vars
rem cleanup namespace test.
rem nul redirection stops error output if no test. var is set
for /F "tokens=1 delims==" %%v in ('set test. 2^>nul') do (
set %%v=
)
output from set test. (see above):
test.some.property=3
test.text=asd=f
The most important parts are:
the for-loop with the eol and delims option and
the if-checks that both variables %%a and %%b are set.
What you do in the for-loop with the variable and its value is certainly up to you - assigning to some prefixed variables was just an example. The namespacing approach avoids that any other global variable gets overridden.
For example if you have something like appdata defined in your .properties file.
I'm using this to get rid of an extra config.bat and instead using one .properties file for both the java app and some support batch files.
Works for me, but certainly not every edge case is covered here, so improvements welcome!
Try this
echo off
setlocal
FOR /F "tokens=3,* delims=.=" %%G IN (test.properties) DO ( set %%G=%%H )
rem now use below vars
if "%%G"=="file"
set lfile=%%H
if "%%G"=="path"
set lpath=%%H
if "%%G"=="extension"
set lextention=%%H
echo %path%
endlocal
I know this is ancient post but I would like to expand on toschug's great answer.
If the path in the .properties file would be defined as %~dp0 or any other variable that needs to be expanded first before using it, I recommend doing it the following way:
In the .properties file:
path=%~dp0
In the batch file you can then use it the following way (the code is to be used between the two for(s) defining one <=> cleanup one):
if "!test.path!" NEQ "" (
echo Not expanded path: !test.path!
call :expand !test.path! test.path
)
echo test.path expanded: !test.path!
pause
:expand
SET "%~2=%~1"
GOTO :EOF
Don't forget to use (at the start of the batch file):
SETLOCAL ENABLEDELAYEDEXPANSION
you can try this:
#ECHO OFF
#SETLOCAL
FOR /F "tokens=1* delims==" %%A IN (test.properties) DO (
ECHO %%A = %%B
)
#ENDLOCAL
I need to be able to load the entire contents of a text file and load it into a variable for further processing.
How can I do that?
Here's what I did thanks to Roman Odaisky's answer.
SetLocal EnableDelayedExpansion
set content=
for /F "delims=" %%i in (test.txt) do set content=!content! %%i
echo %content%
EndLocal
If your set command supports the /p switch, then you can pipe input that way.
set /p VAR1=<test.txt
set /? |find "/P"
The /P switch allows you to set the value of a variable to a line of
input entered by the user. Displays the specified promptString before
reading the line of input. The promptString can be empty.
This has the added benefit of working for un-registered file types (which the accepted answer does not).
Use for, something along the lines of:
set content=
for /f "delims=" %%i in ('filename') do set content=%content% %%i
Maybe you’ll have to do setlocal enabledelayedexpansion and/or use !content! rather than %content%. I can’t test, as I don’t have any MS Windows nearby (and I wish you the same :-).
The best batch-file-black-magic-reference I know of is at http://www.rsdn.ru/article/winshell/batanyca.xml. If you don’t know Russian, you still could make some use of the code snippets provided.
You can use:
set content=
for /f "delims=" %%i in ('type text.txt') do set content=!content! %%i
Can you define further processing?
You can use a for loop to almost do this, but there's no easy way to insert CR/LF into an environment variable, so you'll have everything in one line. (you may be able to work around this depending on what you need to do.)
You're also limited to less than about 8k text files this way. (You can't create a single env var bigger than around 8k.)
Bill's suggestion of a for loop is probably what you need. You process the file one line at a time:
(use %i at a command line %%i in a batch file)
for /f "tokens=1 delims=" %%i in (file.txt) do echo %%i
more advanced:
for /f "tokens=1 delims=" %%i in (file.txt) do call :part2 %%i
goto :fin
:part2
echo %1
::do further processing here
goto :eof
:fin
To read in an entire multi-line file but retain newlines, you must reinsert them. The following (with '<...>' replaced with a path to my file) did the trick:
#echo OFF
SETLOCAL EnableDelayedExpansion
set N=^
REM These two empty lines are required
set CONTENT=
set FILE=<...>
for /f "delims=" %%x in ('type %FILE%') do set "CONTENT=!CONTENT!%%x!N!"
echo !CONTENT!
ENDLOCAL
You would likely want to do something else rather than echo the file contents.
Note that there is likely a limit to the amount of data that can be read this way so your mileage may vary.
Create a file called "SetFile.bat" that contains the following line with no carriage return at the end of it...
set FileContents=
Then in your batch file do something like this...
#echo off
copy SetFile.bat + %1 $tmp$.bat > nul
call $tmp$.bat
del $tmp$.bat
%1 is the name of your input file and %FileContents% will contain the contents of the input file after the call. This will only work on a one line file though (i.e. a file containing no carriage returns). You could strip out/replace carriage returns from the file before calling the %tmp%.bat if needed.
for /f "delims=" %%i in (count.txt) do set c=%%i
echo %c%
pause