Batch For Variables Printing Registry CSV - variables

When querying the below via cmd
REG QUERY "HKCU\Printers\Connections"
The output is:
HKEY_CURRENT_USER\Printers\Connections\,,xxx-SD-KDP11,Colour
HKEY_CURRENT_USER\Printers\Connections\,,xxx-SD-KDP11,Mono
However when running the Batch file containing code below
#echo OFF
setlocal enableextensions enabledelayedexpansion
echo ============================
echo Network Printers ...
if exist network_printers.txt del network_printers.txt
if exist network_printers2.txt del network_printers2.txt
set reg_keys=
set blank=
set printers_network_paths=
set printers_network_types=
REG QUERY "HKCU\Printers\Connections" > network_printers.txt
for /f "tokens=* delims=" %%A in ('type network_printers.txt') do set network_printers_init=!network_printers_init! %%A
echo !network_printers_init! > network_printers2.txt
echo !network_printers_init!
pause
for /f "usebackq tokens=1,* delims=, skip=4" %%a in ('network_printers2.txt') do (
set reg_keys = !reg_keys! %%a
)
for /f "tokens=2,* delims=, skip=4" %%a in ('type network_printers2.txt') do (
set blank = !blank! %%b
)
for /f "tokens=3,* delims=, skip=4" %%a in ('type network_printers2.txt') do (
set printers_network_names = !printers_network_names! %%c
)
for /f "tokens=4,* delims=, skip=4" %%a in ('type network_printers2.txt') do (
set printers_network_types = !printers_network_types! %%d
)
echo reg_keys: !reg_keys!
echo blank: !blank!
echo Network Printers paths: !printers_network_names!
echo Network Printers types: !printers_network_types!
echo Network Printers paths: !printers_network_names! >> %file%
echo Network Printers types: !printers_network_types! >> %file%
pause
the .csv file produced has nothing for !printers_network_names! and !printers_network_types!
Also the echo lines show nothing being stored in the last 4 variables.
Please advise?

In a for /f loop, "skip=4" means skip 4 lines, but network_printers2.txt only contains one line.
There's some other stuff that can be improved. Mainly, when you set a variable in batch scripting, you should set "varname=string", quoted like that and with no spaces surrounding the =. You can also do what you need without the intermediate text files and the useless use of type.
I'm not entirely certain what you want the end result to be, but it looks like you're making your script a whole lot more complicated than it needs to be.
#echo OFF
setlocal enableextensions enabledelayedexpansion
echo ============================
echo Network Printers ...
for /f "tokens=2* delims=," %%A in ('REG QUERY "HKCU\Printers\Connections"') do (
set "printers_network_names=!printers_network_names! %%A"
set "printers_network_types=!printers_network_types! %%B"
)
echo Network printer paths: !printers_network_names!
echo Network printer types: !printers_network_types!
Result:
============================
Network Printers ...
Network printer paths: xxx-SD-KDP11 xxx-SD-KDP11
Network printer types: Colour Mono

Related

for /f loop "tokens and delimiters" didn't work with variables (batch file)

recently I was making a batch file I ran into a problem,
when I made a for /f loop, I used a variable in "tokens", like this example:
for /f "delims= tokens=!count2!" %%a in ('type test.txt 2^>nul') do (
like you can see, i have the variable !count2!, in the loop.
and when i tested it, it displayed !count2!" was unexpected at this time. And I dont know why?
can anyone help?
here is the full code of what I have tried:
#echo off
setlocal enableextensions enabledelayedexpansion
set "count1=0"
set "count2=0"
for /l %%b in (1 1 10) do (
set /a "count2+=1"
set /a "count1+=1"
for /f "delims= tokens=!count2!" %%a in ('type test.txt 2^>nul') do (
set "str!count1!=%%a"
)
)
echo !str1! !str2! !str3! !str4!
pause
by the way, test.txt contains test hello # ###
and, I want to set test, hello, # and ### as their own variable (str1, str2, str3 and str4).
and yes I have tried to do it with % instead of !
tell me if i wasn't clear enough!
thanks for all help :)
why bothering with tokens?
#echo off
setlocal enabledelayedexpansion
set /a count=0
for /f "delims=" %%i in (test.txt) do for %%j in (%%i) do (
set /a count+=1
set str!count!=%%j
)
set str

CMD: extract part of a filename and use it as variable

I ripped my CDs with EAC to CUE+WAV files, added cover art and all my files are in the same folder with filenames pattern "Album artist - Album title", for ex.:
Clannad - Legend.wav/cue/jpg
David Bowie - Best Of Bowie [Disc 1].wav/cue/jpg
David Bowie - Best Of Bowie [Disc 2].wav/cue/jpg
I'm new to this so I wrote a simple CMD batch to convert my music to FLAC format, but it requires manual copying and pasting of the actual wav/cue/jpg filenames and input of album artist, disc no. and total disc no. for their corresponding tags. It cannot be stored in cuesheet file for some reason, but in my case I have them in filenames as you can see above).
ECHO WAV/CUE/JPG FILENAME
SET /P "input="
ECHO ALBUMARTIST
SET /P "albumartist="
ECHO DISCNUMBER
SET /P "discnumber="
ECHO TOTALDISCS
SET /P "totaldiscs="
flac.exe -0 --picture="D:\Music\%input%.jpg" --tag-from-file="CUESHEET=D:\Music\%input%.cue" -T "ALBUMARTIST=%albumartist%" -T "DISCNUMBER=%discnumber%" -T "TOTALDISCS=%totaldiscs%" "D:\Music\%input%.wav"
My question is about automation of converting all my ripped albums. How can I extract album artist/disc no./total disc no. info from filenames and loop that for every .wav file?
#ECHO OFF
SETLOCAL
SET "destdir=U:\destdir"
PUSHD "%destdir%"
:: Find all .jpgs where there is a .wav and .cue with the same name
FOR /f "delims=" %%a IN ('dir /b /a-d *.jpg') DO IF EXIST "%%~na.wav" IF EXIST "%%~na.cue" (
FOR %%b IN (input albumartist discnumber totaldiscs) DO SET "%%b="
SET "input=%%~na"
FOR /f "delims=-" %%b IN ("%%a") DO SET "albumartist=%%b"
FOR /f "tokens=2delims=[]" %%b IN ("%%a") DO SET "disc=%%b"
IF DEFINED disc (
FOR /f "tokens=1delims=[]" %%d IN ("%%a") DO FOR /f %%c IN ('dir /b "%%d[*.wav"') DO SET /a totaldiscs+=1
)
CALL :gflac
)
POPD
GOTO :EOF
:gflac
:: remove trailing spaces from INPUT
IF "%albumartist:~-1%"==" " SET "albumartist=%albumartist:~0,-1%"&GOTO gflac
:: presume default for disc and totaldiscs
IF DEFINED disc (FOR /f "tokens=2" %%d IN ("%disc%") DO SET /a disc=%%d) ELSE (SET /a disc=1)
IF NOT DEFINED totaldiscs SET /a totaldiscs=1
ECHO( flac.exe -0 --picture="D:\Music\%input%.jpg" --tag-from-file="CUESHEET=D:\Music\%input%.cue" -T "ALBUMARTIST=%albumartist%" -T "DISCNUMBER=%discnumber%" -T "TOTALDISCS=%totaldiscs%" "D:\Music\%input%.wav"
GOTO :eof
You would need to change the setting of destdir to suit your circumstances.
The above will merely echo the required flac line. I left it as you posted but set the scant test data you posted up as I interpret it (ie. there is a set of 3 files) on my U: drive.
Sadly, you've given us insufficient information. I've assumed that you need all three files to be present, and the default for totaldiscs is 1.
First, look for all .jpgs, and if there is a corresponding .wav and .cue then process for flac generation as follows:
Set input to the name part of the .jpg found
set albumartist to the first part of the filename, up to the -
get the [disc n] string if it's present
count the number of .wavs that start with the filename up to the [
generate the flac line.
Within the generation of the flac line, we strip off the trailing spaces from input, convert disc n to n or set disc to 1 (although this information may not be needed), and set the totaldiscs to 1 if it's not been calculated.
You don't say what flac produces as output, but I'd suggest that you further gate that filetype so that the procedure doesn't run if the %input%.finalproductwhateverthatis file is present.
[edited per dbenham's comments]
This is very similar to Magoo's answer, with some bug fixes, and everything is done in one master loop without a CALL. As with Magoo's answer, modify your destination folder at the beginning to suit your needs.
#echo off
:: Delayed expansion must be disabled to protect ! when expanding FOR variables.
:: It is normally disabled by default, but I'm making it explicit, just to be sure.
setlocal disableDelayedExpansion
:: Define where source files are coming from
set "source=D:\Music"
:: Define where output should be stored
set "destination=D:\Music"
pushd "%destination%"
:: Iterate each .wav file (A) and only proceed if .jpg and .cue also exists
for /f "delims=" %%A in ('dir /b /a-d "%source%\*.wav"') do if exist "%source%\%%~nA.jpg" if exist "%source%\%%~nA.cue" (
%= Get base name with path, but without extension =%
set "file=%source%\%%~nA"
%= Extract "artist - album " (B) and "Disc #" (C) from base name (~nA) =%
for /f "delims=[] tokens=1,2" %%B in ("%%~nA") do (
%= Extract "artst " (D) from "artist - abum ". (~nxD) trims trailing space =%
for /f "delims=-" %%D in ("%%B") do set "artist=%%~nxD"
%= Extract the number (E) from "Disc #", use 1 as default if not there =%
set "disc=1"
for /f "tokens=2" %%E in ("%%C") do set "disc=%%E"
%= Count the number of discs (F), will be 0 if no [Disc #] =%
%= The [ is appended to name to prevent something like "Greatest Hits 2" from matching "Greatist Hits" =%
for /f %%F in ('dir /b /a-d "%source%\%%B[*.wav" 2^>nul ^|find /c /v ""') do set "count=%%F"
%= temporarily enable delayed expansion to access variables set within loop =%
setlocal enableDelayedExpansion
%= Set count to 1 if no [Disc #] =%
if !count! equ 0 set /a count=1
flac.exe -0 --picture="!file!.jpg" --tag-from-file="CUESHEET=!file!.cue" -T "ALBUMARTIST=!artist!" -T "DISCNUMBER=!disc!" -T "TOTALDISCS=!count!" "!file!.wav"
%= pop the setlocal stack to get back to state at beginning of loop =%
endlocal
)
)
popd
You may want to add a check to only proceed if the FLAC file does not already exist so you can run the script multiple times without reprocessing files. The outer loop would look something like this, but I can't be sure since I don't know the format of the output file name:
for /f "delims=" %%A in ('dir /b /a-d "%source%\*.wav"') do if exist "%source%\%%~nA.jpg" if exist "%source%\%%~nA.cue" if not exist "%destination%\%%~nA.flac" (
The logic is much simpler using my JREPL.BAT utility if you understand regular expressions:
#echo off
:: Delayed expansion must be disabled to protect ! when expanding FOR variables.
:: It is normally disabled by default, but I'm making it explicit, just to be sure.
setlocal disableDelayedExpansion
:: Define where source files are coming from
set "source=D:\music"
:: Define where output should be stored
set "destination=D:\music"
pushd "%destination%"
:: Iterate all *.wav and use JREPL to format result as "fullFileName|artist - album|artist|Disc#"
:: %%A %%B %%C %%D
:: Only proceed if .jpg and .cue also exist
for /f "tokens=1-4 delims=|" %%A in (
'dir /b /a-d "%source%\*.wav"^|jrepl "^((.+?) - .+?)(?:\[Disc (\d+)])?\.wav$" "$&|$1|$2|$3" /i'
) do if exist "%%~nA.jpg" if exist "%%~nA.cue" (
%= disc and count are both 1 if %%D is empty =%
if "%%D" equ "" (
flac.exe -0 --picture="%source%\%%~nA.jpg" --tag-from-file="CUESHEET=%source%\%%~nA.cue" -T "ALBUMARTIST=%%C" -T "DISCNUMBER=1" -T "TOTALDISCS=1" "%source%\%%A"
%= else count the number of .wav files =%
) else for /f %%E in ('dir /b /a-d "%%B[*.wav"^|find /c /v ""') do (
flac.exe -0 --picture="%source%\%%~nA.jpg" --tag-from-file="CUESHEET=%source%\%%~nA.cue" -T "ALBUMARTIST=%%C" -T "DISCNUMBER=%%D" -T "TOTALDISCS=%%E" "%source%\%%A"
)
)
popd
Again, you can add an IF to the outer loop to proceed only if the .flac file does not already exist in the destination.

FINDSTR in FOR loop with variables as strings (Batch File)

It's my first post here, unfotrtunately question to you instead of help.
I'm writing small program which moves text and pdf files when string is found in text file.(1.txt, 1.txt.pdf ...) It was working very good when i had variables manually set in batch like this :
set c1=xxx
set p1=c:\test\xxx\
set c2=yyy
set p2=c:\test\yyy\
FOR /f "tokens=*" %%A IN ('FINDSTR /i /m "%c1%" "c:\test\*.txt"') DO (
IF "%ERRORLEVEL%"=="0" MOVE %%A "%p1%">nul
MOVE %%A.pdf %p1%
FOR /f "tokens=*" %%A IN ('FINDSTR /i /m "%c2%" "c:\test\*.txt"') DO (
IF "%ERRORLEVEL%"=="0" MOVE %%A "%p2%">nul
MOVE %%A.pdf %p2%
Now I'm trying to use input file with variables :
for /F "delims=^ tokens=1,2" %%A in (c:\test\db\input.cdb) do (
SET /A vidx=!vidx! + 1
set c!vidx!=%%A & set p!vidx!=%%B
It works good, but the problem starts when I try to use for loop for all this variables. Literally search for all (c1,c2,c3...) variables and move them to (p1,p2,p3,...) paths.
Input.cdb looks like this :
xxx ^ c:\test\xxx
yyy ^ c:\test\yyy
Code:
setlocal ENABLEDELAYEDEXPANSION
set vidx=0
for /F "delims=^ tokens=1,2" %%A in (c:\test\db\input.cdb) do (
SET /A vidx=!vidx! + 1
set c!vidx!=%%A & set p!vidx!=%%B
FOR /f "tokens=*" %%D IN ('FINDSTR /i /m "%c!vidx!%" "c:\test\*.txt"') DO (
IF "%ERRORLEVEL%"=="0" MOVE %%D "%p!vidx!%">nul
MOVE "%%D.pdf" "%p!vidx!%"
ECHO %%D File is being procesed now
)
)
I don't know why this code doesn't work, maybe because there is loop inside loop?
Or how to create loop to do the same from 0 to how many lines of variables has been read from input.cdb?
I've tried to run this in separate for loop with temporary variable but it's still not using my string and path variables.
Thank you in advance for any help!
With Regards
Blackfusion
Ugh. More than one problem, and what is the appropriate solution?
First item is a matter of logical design. Let's assume that the batch worked as intended. c!vidx! would be set to %%A and p!vidx! to %%B, so unless there's some unpublished use for c... and p... then you could simply substitute as follows:
setlocal ENABLEDELAYEDEXPANSION
for /F "delims=^ tokens=1,2" %%A in (c:\test\db\input.cdb) do (
FOR /f "tokens=*" %%D IN ('FINDSTR /i /m "%%A" "c:\test\*.txt"') DO (
IF "%ERRORLEVEL%"=="0" MOVE %%D "%%B">nul
MOVE "%%D.pdf" "%%B"
ECHO %%D File is being procesed now
)
)
Now - there's a common fundamental misconception about %var% where var is any variable (including %ERRORLEVEL% and %C!vidx!%...) - a %VAR% occurring in a compound statement (or "block") - within the parentheses if a FOR...DO (in here) or IF...(here) ELSE (or here) is replaced with that variable's value at the time the outermost statement is parsed - before it is executed. If delayedexpansion is invoked (as you have) then !var! refers to the run-time value and %var% to the parse-time value.
Hence, if "%errorlevel%"=="0" would be evaluated according to the state of errorlevel when the for...%%A was parsed, not the value as set by the findstr.
This can be corrected by
setlocal ENABLEDELAYEDEXPANSION
for /F "delims=^ tokens=1,2" %%A in (c:\test\db\input.cdb) do (
FOR /f "tokens=*" %%D IN ('FINDSTR /i /m "%%A" "c:\test\*.txt"') DO (
IF not errorlevel 1 MOVE %%D "%%B">nul
MOVE "%%D.pdf" "%%B"
ECHO %%D File is being procesed now
)
)
Where IF not errorlevel 1 is interpreted as if the CURRENT (run-time) errorlevel is NOT (1 or greater than 1)

How to delete a line of a text file, given the line number using batch (.bat) script?

I want to write a batch script where the user can enter the line number and the script will delete that line of a text file.
Eg: tmp.txt
1. aaa
2. bbb
3. ccc
4. ddd
I want when i execute my script and user inputs 3, the tmp.txt to be
1. aaa
2. bbb
4. ddd
I am trying something like this:
#ECHO OFF
SET /P LINENUMBER=Enter the Line No:
FOR /F "tokens=1* delims=[]" %%a IN ('FIND /n /v "" ^< tmp.txt') DO (
IF %%a equ %LINENUMBER% (
????????????????????
)
)
You cannot modify the file directly. You must create a new file with the desired content and then replace the original file with the new file.
You create the new file by redirecting output and ECHOing the desired content. I use ECHO(%%b in case %%b is empty because the line was blank. ECHO %%b would produce ECHO is off. if b is empty. Most people use ECHO., but that can fail under esoteric conditions. ECHO( will never fail.
You use MOVE to replace the original file with the new.
You can eliminate the need to check for the number within your FOR /F loop by using FINDSTR after FIND to filter out the unwanted line.
Note that your code, as written so far, will strip any leading [ and ] characters from each line. Because the line filter is applied before the FOR iteration, you can improve the situation slightly by setting DELIMS to ] only.
#ECHO OFF
SET /P LINENUMBER=Enter the Line No:
>tmp.txt.new (
FOR /F "tokens=1* delims=]" %%a IN (
'FIND /n /v "" ^<tmp.txt^|FINDSTR /VLB "[%LINENUMBER%]"'
) DO ECHO(%%b
)
>nul MOVE /y tmp.txt.new tmp.txt
If any of your original lines already begin with ] then you can use FINDSTR instead of FIND to introduce the line number. That uses nn: format instead of [nn]. This solution will strip leading : from your lines.
#ECHO OFF
SET /P LINENUMBER=Enter the Line No:
>tmp.txt.new (
FOR /F "tokens=1* delims=:" %%a IN (
'FINDSTR /n "^" tmp.txt^|FINDSTR /VLB "%LINENUMBER%:"'
) DO ECHO(%%b
)
>nul MOVE /y tmp.txt.new tmp.txt
If your text file contains lines that begin both with : and ] then you can't use FOR /F to parse out the line number. Instead you use search and replace. Delayed expansion is toggled on and off within the loop to protect any ! that may exist in the file.
#ECHO OFF
setlocal disableDelayedExpansion
SET /P LINENUMBER=Enter the Line No:
>tmp.txt.new (
FOR /F "delims=" %%a IN (
'FINDSTR /n "^" tmp.txt ^| FINDSTR /VLB "%LINENUMBER%:"'
) DO (
set "ln=%%a"
setlocal enableDelayedExpansion
echo(!ln:*:=!
endlocal
)
)
>nul MOVE /y tmp.txt.new tmp.txt
try out this:
#echo off & setlocal
set "InFile=Z:\Text.txt"
set "OutFile=Z:\Erg.txt"
set /p LineToDelete=
if exist "%OutFile%" del "%OutFile%"
for /f "tokens=1* delims=:" %%i in ('findstr /n $ "%InFile%"^|findstr /b "%LineToDelete%:"') do findstr /v /b /c:"%%j" "%InFile%">>"%OutFile%"

wmic variables from txt file

I'm trying to get the output of the WMIC command to assign variables to each line.
I'm trying to get the out put to look like this:
1 first program installed
2 second program installed
3 third program installed
4 fourth program installed
5 ...etc
#Echo off
wmic /output:file.txt product get name /format:csv
rem wmic product get name
#Echo Off
SetLocal EnableDelayedExpansion
Set n=
Set _InputFile=c:\users\jorge\desktop\file.txt
For /F "tokens=*" %%I IN (%_InputFile%) DO (
Set /a n+=1
Set _var!n!=%%I
)
:: This line will display the variables just assigned
:: For testing only, delete when not needed
Set _
EndLocal
pause
This won't work because wmic will give you Unicode file that for /f can not read (see here). Workaround is to use ('type file') instead:
#Echo off
:: not really need a csv here...
wmic /output:file.txt product get name /format:table
Set n=0
:: Suggest to use internal call :label rather than delayed expansion
For /F "tokens=* skip=1 delims=" %%I IN ('type file.txt') DO #call :Assign %%I
Set _
pause
goto :EOF
:Assign
Set /a n+=1
Set _var%n% = %*
goto :EOF