I need to create a batch file to create a folder from substring of a filename
example filename : txt_abc_123
create a folder with the name between "_" (abc)
and the filename with (123)
any help will be much appreciated.
look into the help for FOR /F, something like FOR /F "tokens=2,3* delims=_" %%a in ("txt_abc_123 ") will yield abc in %%a and 123 in %%b.
If you know you only have two underscores in the filename, here's a solution:
#echo off
setlocal enabledelayedexpansion
set xfile=txt_abc_123
set n=0
set zz=0
set before=
set file=
set folder=
:begin
set yy=!xfile:~%n%,1!
set /a n=n+1
if "%yy%"=="_" (
if %zz% EQU 0 (
set zz=1
) ELSE (
set zz=2
)
)
if %zz% EQU 0 (
set before=%before%%yy%
)
if %zz% EQU 1 (
if not "%yy%"=="_" (
set folder=%folder%%yy%
)
)
if %zz% EQU 2 (
if not "%yy%"=="_" (
set file=%file%%yy%
)
)
if not "%yy%"=="" (
goto begin
)
echo Folder: %folder%
echo File: %file%
if not exist %folder%\ (md %folder%)
move %xfile% %folder%\%file%
endlocal
If you don't know you'll have only two underscores, this would need to be modified slightly.
If you want to run this for multiple files, replace the txt_abc_123 above with %1 , save to file batchfilename.bat, and run with
for %i in (*_*_*) do (
batchfilename.bat %i
)
Related
I am trying to search through a text file for keywords, then insert a number of lines after a specific line/keyword (not end of file).
My code can find the keywords, however I am struggling to add the lines. My code adds the line to the end of the file, so the bit I need help with is after :ADD THE TEXT.
myfile.text looks like:
QFU;
text2;
LastUpdate=20180323;
text3;
I would like to add a list of static lines after LastUpdate, which makes the file look like:
QFU;
text2;
LastUpdate=20180323;
Inserted text1
Inserted text2
text3;
This is my code:
#echo
SET /A COND1=0
for /F "tokens=*" %%i in (myfile.txt) do call :process %%i
goto thenextstep
:process
set VAR1=%1
IF "%VAR1%"=="QFU" SET /A COND1=1
IF "%VAR1%"=="QFU" (
msg * "QFU line found !!"
)
:If QFU line is found then look for Last update
IF "%COND1%"=="1" IF "%VAR1%"=="LastUpdate" (
msg * "LastUpdate line found !!"
:ADD THE TEXT
echo. text to be added>>myfile.txt
:reset COND1 to 0
set /A COND1=0
)
#echo off
setlocal enabledelayedexpansion
call :get_insert_index
if not defined index (
>&2 echo index not defined.
exit /b 1
)
set "i=0"
(
for /f "tokens=*" %%A in (myfile.txt) do (
set /a "i+=1"
echo %%A
for %%B in (%index%) do if !i! equ %%B (
echo --- INSERT
)
)
) > myupdate.txt
exit /b
:get_insert_index
setlocal enabledelayedexpansion
set "i=0"
set "qfu="
set "total="
for /f "tokens=*" %%A in (myfile.txt) do (
set /a i+=1
set "line=%%~A"
if "%%~A" == "QFU;" (
set /a "qfu=!i! + 1"
) else if "!line:~,11!" == "LastUpdate=" (
if defined qfu (
if !i! gtr !qfu! (
if defined total (set total=!total! !i!) else set total=!i!
set "qfu="
)
)
)
)
endlocal & set "index=%total%"
exit /b
This will insert text after the 1st line starting with LastUpdate=,
after the line of QFU;, but not the line starting with LastUpdate=
which is the next line after QFU;.
The label :get_insert_index is called and uses a for loop
to read myfile.txt to get the line index of LastUpdate=
mentioned in the above paragraph.
The variable qfu stores the line index + 1 of QFU; so
LastUpdate= cannot be matched on the next line.
If gfu and LastUpdate= is found and the line index is
greater then gfu, then the line index is appended to total.
qfu is undefined to avoid further matches to LastUpdate=
until QFU; is matched again.
The loop will end and the global variable index is set the
value of total. The label returns control back to the caller.
index is checked if defined at the top of the script after
the call of the label.
The top for loop reads myfile.txt and echoes each line read.
The nested for loop checks the index variable to match the
current line index and if equal, will echo the new text.
The echoes are redirected to myupdate.txt.
Used substitution of "!line:~,11!" so view set /? for help.
Used enabledelayedexpansion so view setlocal /? for help.
Text using ! may find ! being interpreted as a variable
so avoid using !.
Used gtr which can be viewed in if /?. gtr is
"Greater than".
Alternative to avoid creation of an index:
#echo off
setlocal enabledelayedexpansion
set "i=0"
set "gfu="
for /f "tokens=*" %%A in (myfile.txt) do (
set /a i+=1
set "line=%%~A"
>> myupdate.txt echo(%%A
if "%%~A" == "QFU;" (
set /a "qfu=!i! + 1"
) else if "!line:~,11!" == "LastUpdate=" (
if defined qfu (
if !i! gtr !qfu! (
>> myupdate.txt echo --- INSERT
set "qfu="
)
)
)
)
exit /b
>> myupdate.txt echo(%%A writes each line.
>> myupdate.txt echo --- INSERT writes new line to insert.
If system memory permits based on file size, this is much faster:
#echo off
setlocal enabledelayedexpansion
set "i=0"
set "gfu="
(
for /f "tokens=*" %%A in (myfile.txt) do (
set /a i+=1
set "line=%%~A"
echo(%%A
if "%%~A" == "QFU;" (
set /a "qfu=!i! + 1"
) else if "!line:~,11!" == "LastUpdate=" (
if defined qfu (
if !i! gtr !qfu! (
echo --- INSERT
set "qfu="
)
)
)
)
) > myupdate.txt
exit /b
Used on 2.74 MB file, Time reduced from 70s to 21s. The write handle to myupdate.txt remains open for the entire loop, thus the write is cached.
I have a .bat file like this:
#echo OFF
if "%1" == "" (
set pattern=*
) else (
set pattern=%1
)
for %%g in (%pattern%) do echo %%g
Executing listfile.bat setenv*.bat, it outputs something like:
setenv-win7x64-chk.bat
setenv-win7x64-fre.bat
setenv-winxp-chk.bat
setenv-winxp-fre.bat
My question is: How can I make it output like:
[1] setenv-win7x64-chk.bat
[2] setenv-win7x64-fre.bat
[3] setenv-winxp-chk.bat
[4] setenv-winxp-fre.bat
Is there a secret variable that tells me the current loop-index? -- just like Autohotkey's A_Index variable.
The answer is "no", but you may add a counting variable in a very simple way:
#echo OFF
setlocal EnableDelayedExpansion
if "%1" == "" (
set pattern=*
) else (
set pattern=%1
)
set i=0
for %%g in (%pattern%) do (
set /A i+=1
echo [!i!] %%g
)
I suggest letting a tool do the enumeration for simplicity:
( for %%g in (%pattern%) do #echo %%g ) | find /n /v ""
In the office we have a extense and well defined file structure , and i have to create a hundreds of directories with the same name but differing in the last numbers.
directory0001
directory0002
...
directory0324
this is what i have done:
SET B=0001
SET C=0324
:while1
IF NOT %B%==%C%
(
echo "first loop"
SET COUNTER=0
IF NOT %COUNTER%=1
(
echo "Secoond loop"
mkdir "C:\pathfile\directory00"%B%
SET COUNTER==1
)
else()
SET B=%B%+1
goto :while1
)
else
(
)
I'm not sure whether i'm using properly the operators or not, i'm using what i've found in different posts.
-i'm using windows terminal to debugg the code, there is a better way?
There is a FOR loop for exactly this, incrementing a count from one value to the end value:
for /L %%i in (1,1,324) do if %%i LEQ 9 ( md "C:\pathfile\directory000%i" ) else if %%i LEQ 99 ( md "C:\pathfile\directory00%i" ) else ( md "C:\pathfile\directory0%%i" )
This will start at 1, increment by 1, until 324 is reached. The IF statement is only needed for formatting leading zeroes.
Edit:
this is the complete code with proper indentation so that you (as a novice) can understand the flow more easily:
#echo off
SETLOCAL ENABLEEXTENSIONS
REM enable cmd extensions so that mkdir/md will create all intermediate folders
SET first=1
SET last=324
REM numeric extension will be appended with 4 places to this foldername
SET folder=C:\users\goofy\manydirs\directory
FOR /L %%i in (%first%,1,%last%) DO (
IF %%i LEQ 9 (
mkdir %folder%000%%i
) ELSE IF %%i LEQ 99 (
mkdir %folder%00%%i
) ELSE IF %%i LEQ 999 (
mkdir %folder%0%%i
) ELSE (
mkdir %folder%%%i
)
)
I am new to using batch files so could someone please help me split a string i am getting from a file.
I am using %USERPROFILE% to get my string.
The string is: "C:\Users\nicholas"
I would like to keep the C:\ part, but get rid of the \Users\nicholas part.
for /f "tokens=2 delims=\" %A in ('set userprofile') do echo %A\
See for /?
Also
echo %userprofile:~0,3%
If you carefully read the output of set /?, you'll find the answer:
May also specify substrings for an expansion.
%PATH:~10,5%
would expand the PATH environment variable, and then use only the 5
characters that begin at the 11th (offset 10) character of the expanded
result.
So, you can use something like this to get the first 3 characters of your string:
> echo %userprofile:~0,3%
C:\
I As you need the drive where where the users are located you can use directly
%systemdrive% variable - this is the drive where the windows is installed
II the easiest way to get a drive from path:
for %%a in ("%userprofile%") do echo %%~da\
%~da - expands a path to its drive only
III over-complicated but powerful way (split function that can be used for a different things):
#echo off
call :split "%userprofile%" "\" 1 drive
echo %drive%\
goto :eof
:split [%1 - string to be splitted;%2 - split by;%3 - possition to get; %4 - if defined will store the result in variable with same name]
::http://ss64.org/viewtopic.php?id=1687
setlocal EnableDelayedExpansion
set "string=%~2%~1"
set "splitter=%~2"
set /a position=%~3
set LF=^
rem ** Two empty lines are required
echo off
for %%L in ("!LF!") DO (
for /f "delims=" %%R in ("!splitter!") do (
set "var=!string:%%~R%%~R=%%~L!"
set "var=!var:%%~R=%%~L!"
if "!var!" EQU "!string!" (
echo "%~1" does not contain "!splitter!" >&2
exit /B 1
)
)
)
if "!var!" equ "" (
endlocal & if "%~4" NEQ "" ( set "%~4=")
)
if !position! LEQ 0 ( set "_skip=" ) else (set "_skip=skip=%position%")
for /f "eol= %_skip% delims=" %%P in (""!var!"") DO (
if "%%~P" neq "" (
set "part=%%~P"
goto :end_for
)
)
set "part="
:end_for
if not defined part (
endlocal
echo Index Out Of Bound >&2
exit /B 2
)
endlocal & if "%~4" NEQ "" (set %~4=%part%) else echo %part%
exit /b 0
I have a text file that have unknown number of lines , some lines begins with patterns , I want to join the lines that begins with patterns with the next line , so for example
name=jimmy
age=19 id=23423 site=www.xxx.com
bla bla
name=katy
age=15 id=234543 site=www.yyy.com
name=ross
age=29 id=54564 site=www.ZZZZ.com
the output should be
name=jimmy age=19 id=23423 site=www.xxx.com
bla bla bla
name=katy age=15 id=234543 site=www.yyy.com
name=ross age=29 id=54564 site=www.ZZZZ.com
so the pattern is 'name' and it should join next line
I thougt to use sed but I dont know how
help please
Well, here's a straightforward script:
#echo off
setlocal enabledelayedexpansion
set "INPUT_FILE=input.txt"
set "OUTPUT_FILE=output.txt"
set prev=
for /f "tokens=*" %%f in (%INPUT_FILE%) do (
for /f "tokens=1,2 delims==" %%g in ("%%f") do (
if "!prev!" neq "" (
echo !prev! %%f >>%OUTPUT_FILE%
set prev=
) else (
if "%%g" equ "name" (
set prev=%%f
) else (
echo %%f >>%OUTPUT_FILE%
set prev=
)
)
)
)
#echo off
setlocal EnableDelayedExpansion
set pattern=name
set patternLen=4
call :ProcessFile < input.txt > output.txt
goto :EOF
:ProcessFile
set line=
set /P line=
if not defined line exit /B
if "!line:~0,%patternLen%!" equ "%pattern%" (
set /P nextLine=
set "line=!line! !nextLine!"
)
echo !line!
goto ProcessFile
Previous Batch file have the problem that it ends at the first empty line in the input file. However, this problem may be fixed if needed.