How to use printui.exe with a value containing the printer name - for-loop

Im trying to make a small script that will automatically remove all printers except the ones that are part of the OS (Microsoft to PDF, OneNote, etc).
I tried to filter them one by one in a for loop but for some reasons, it say that it wont recognise the printer name.
I echoed the result instead to see what goes in and the name of the printer seemed to be right.
So im thinking that there could be a newline character at the end of my value and I would like to know how to make sure that the name is correctly outputed in the printui.exe command.
REM Loop that will go through all printer name that are installed on the computer
for /f "tokens=*" %%a in ('wmic printer get name') do (
REM Verify if the printer name contain "Microsoft", "OneNote" or "Name"
echo %%a | findstr /i "Microsoft OneNote Name" > nul
if errorlevel 1 (
REM Delete the printer that dosent contain any of the word mentionned before
echo %%a
printui.exe /dl /n %%a
) else (
REM Delete nothing
)
)
The code above resulted in a error messagebox saying that it don't recognise the printer, that it might be disconnected or the printer name is wrong. (which is not right to me)
I expected the command to work without error and say that the process was completed.

#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
for /f "delims=" %%b in ('wmic printer get name') do for /f "delims=" %%B in ("%%b") do (
REM Verify if the printer name contain "Microsoft", "OneNote" or "Name"
echo %%B | findstr /i "Microsoft OneNote Name" > nul
if errorlevel 1 (
REM Delete the printer that dosent contain any of the word mentionned before
SET "myprinter=%%B"
CALL :mangle
echo %%B --- !myprinter! ---
printui.exe /p /n !myprinter!
) else (
REM Delete nothing
)
)
GOTO :EOF
:: IF the printername myprinter contains spaces, replace with `" "`
:mangle
IF "%myprinter:~-1%"==" " SET "myprinter=%myprinter:~0,-1%"&GOTO mangle
SET "myprinter=!myprinter: =" "!"
GOTO :eof
Always verify against a test directory before applying to real data.
This is a strange one. If the printer name eg HP LaserJet CP 1025 contains spaces, then it must be entered as HP" "LaserJet" "CP" "1025 - and yes, I've double-checked that. Reference to off-site URL: Spiceworks - set up printer
I've used the /p option as I don't want to delete printers.

Related

Setting name of current file being read as variable

Using a for loop in a batch file, from a folder full of xml files, I am trying to parse an xml tag but also the file name of the current file being read.
I have searched and this question seems to be the same as mine, but for linux. I am using windows
Can I get the name of the file currently being read in a for loop?
From other answers on the forum I have put together this, but unsuccessful.
for %%a in (*.xml) do (
for /f "delims=<> tokens=3" %%b in ('findstr /i /c:"<description>" *.xml') do (
echo %%~na^|%%b>>output.txt
)
)
Is it possible to get the xml tag and echo the file name of the file the tag was read from?
kind of like:
for /f "delims=<> tokens=3" %%b in ('findstr /i /c:"<description>" *.xml') do (
echo %~n0^|%%b>>output.txt
)
Except that will echo the bat file name, not the xml name.
Example final output desired (xml name|xml tag)
Atari 2600|Air Raid
Atari 2600|Airlock
Atari 2600|Alien
Nintendo Game Boy|Addams Family
Nintendo Game Boy|Adventure Island
Sega 32X|Blackthorne
Sega 32X|Mortal Kombat II
Appreciate any advice as I am just teaching myself here, I don't mind just being steered in the right direction either.
for /f "delims=<> tokens=3" %%b in ('findstr /i /c:"<description>" "%%a"') do (
should work for you. The current filename is in %%a. Your code would attempt to find the string in all .xml files.
Perhaps findstr /m /i /c:<description>" *.xml may give you a workable base (as a command - not as a replacement findstr command for your batch).
Supplementary after comment
SET "varlist=applicationpath missing notes junk"
FOR %%a IN (%filename1%) DO (
FOR %%w IN (%varlist%) DO SET "%%w="&for /f "delims=<> tokens=3" %%b in ('findstr /i /c:"<%%w>" "%%a"') do SET "%%w=%%b"
)
:: Show resulting values from file
FOR %%w IN (%varlist%) DO SET %%w
I'm assuming that you are using %%a as you will to set up the .xml filename - I just used a fixed text file as the source for testing.
Simply establish a list of the variables you wish to extract and alter the string that findstr locates in the file. Set the variablename to the value from the located line. If not located, leave set to nothing (which is easily tested with an if defined variablename command)

Find in file then move the file

I have an unknown number of text files in a directory which are named as such, ABC1200f1234.EAU, but they are all slightly different. The internal structure of each text file is the same, but the contents are different. Within each file there is a string * SERIAL NUMBER:XXXXX *. For each file the 6 characters following the SERIAL NUMBER: is different. I am trying to search each file to obtain the 6 digits following SERIAL NUMBER: then move that file to a directory named after the 6 digits, e.g. if the 6 digits are A12345 then I want to create a directory named A12345 and move the file there, then move on to the next file until all files have been moved.
The following code gets the 6 digits into %%a but I'm stuck on how to then move the file, before moving onto the next one. I'm sure I'm just missing one small piece of the puzzle.
#ECHO OFF
CLS
cd c\Temp
setlocal enableextensions disabledelayedexpansions
set sourcedir=c:temp
set targetdir=c:\temp\parsed
for /f "tokens=4 delims=*:" %%a in (
'findstr /r "SERIAL NUMBER:" %sourcedir%\*'
) do (
if exists %targetdir%\%%a (
echo Directory already exists
) else mkdir %targerdir%\%%a
)
move %sourcedir%\%%a %targetdir%\%%a
)
I'm sure the last line is the problem because %%a now holds the 6 digit number, not the filename.
Please don't suggest Powershell as that is not an option. I also realise I can use robocopy and remove the check to see if the target directory exists.
Any help you can give would be most appreciated.
I'm assuming for this code that the serial number is directly after the colon with no white space or other characters whcih need to be removed before or after it.
#(setlocal EnableDelayedExpansion
ECHO OFF
CLS
set "sourcedir=c:\temp"
set "targetdir=c:\temp\parsed"
SET "FileGlob=*.EAU"
)
CALL :Main
( Endlocal
EXIT /B
)
:Main
FOR %%_ IN (
"%sourcedir%\%FileGlob%"
) DO (
Echo=processing "%%~_"
FOR /F "Tokens=2 delims=:" %%F IN ('
TYPE "%%~_" ^| FIND /I "SERIAL NUMBER:"
') DO (
ECHO=Found. Serial number "%%F" trimmingbany spaces
FOR /F "Tokens=*" %%f IN ("%%~F") DO (
ECHO=Trimmed serial number "%%~f" stored
SET "_TmpFolder=%%F"
)
)
MD "%TargetDir%\!_TmpFolder!\"
MOVE "%%~_" "%TargetDir%\!_TmpFolder!\%%~nx_"
)
GOTO :EOF
There is not any need to test if the directory you're trying to create exists. Simply do mkdir and pipe the output to nul
NOTE! This example assumes that the Serial Number is on it's own line in the file, seeing as you have not shown an actual example of your text file.
#echo off
set "source=c:\temp"
set "target=c:\temp\parsed"
for %%a in ("%source%\*.EAU") do for /f "tokens=2* delims=:" %%i in ('type "%%~a" ^|findstr /i "serial number"') do (
mkdir "%target%\%%i">nul 2>&1
move "%%~a" "%target%\%%i"
)
As far as overwriting existing files are concerned, that is something you need to decide as I do not know your exact scenario, so did not include additional parameters to the move command.

How can I use a batch file to find a string in a text file and replace the entire line while keeping blank lines [duplicate]

This DOS batch script is stripping out the blank lines and not showing the blank lines in the file even though I am using the TYPE.exe command to convert the file to make sure the file is ASCII so that the FIND command is compatible with the file. Can anyone tell me how to make this script include blank lines?
#ECHO off
FOR /F "USEBACKQ tokens=*" %%A IN (`TYPE.exe "build.properties" ^| FIND.exe /V ""`) DO (
ECHO --%%A--
)
pause
That is the designed behavior of FOR /F - it never returns blank lines. The work around is to use FIND or FINDSTR to prefix the line with the line number. If you can guarantee no lines start with the line number delimiter, then you simply set the appropriate delimiter and keep tokens 1* but use only the 2nd token.
::preserve blank lines using FIND, assume no line starts with ]
::long lines are truncated
for /f "tokens=1* delims=]" %%A in ('type "file.txt" ^| find /n /v ""') do echo %%B
::preserve blank lines using FINDSTR, assume no line starts with :
::long lines > 8191 bytes are lost
for /f "tokens=1* delims=:" %%A in ('type "file.txt" ^| findstr /n "^"') do echo %%B
::FINDSTR variant that preserves long lines
type "file.txt" > "file.txt.tmp"
for /f "tokens=1* delims=:" %%A in ('findstr /n "^" "file.txt.tmp"') do echo %%B
del "file.txt.tmp"
I prefer FINDSTR - it is more reliable. For example, FIND can truncate long lines - FINDSTR does not as long as it reads directly from a file. FINDSTR does drop long lines when reading from stdin via pipe or redirection.
If the file may contain lines that start with the delimiter, then you need to preserve the entire line with the line number prefix, and then use search and replace to remove the line prefix. You probably want delayed expansion off when transferring the %%A to an environment variable, otherwise any ! will be corrupted. But later within the loop you need delayed expansion to do the search and replace.
::preserve blank lines using FIND, even if a line may start with ]
::long lines are truncated
for /f "delims=" %%A in ('type "file.txt" ^| find /n /v ""') do (
set "ln=%%A"
setlocal enableDelayedExpansion
set "ln=!ln:*]=!"
echo(!ln!
endlocal
)
::preserve blank lines using FINDSTR, even if a line may start with :
::long lines >8191 bytes are truncated
for /f "delims=*" %%A in ('type "file.txt" ^| findstr /n "^"') do (
set "ln=%%A"
setlocal enableDelayedExpansion
set "ln=!ln:*:=!"
echo(!ln!
endlocal
)
::FINDSTR variant that preserves long lines
type "file.txt" >"file.txt.tmp"
for /f "delims=*" %%A in ('findstr /n "^" "file.txt.tmp"') do (
set "ln=%%A"
setlocal enableDelayedExpansion
set "ln=!ln:*:=!"
echo(!ln!
endlocal
)
del "file.txt.tmp"
If you don't need to worry about converting the file to ASCII, then it is more efficient to drop the pipe and let FIND or FINDSTR open the file specified as an argument, or via redirection.
There is another work around that completely bypasses FOR /F during the read process. It looks odd, but it is more efficient. There are no restrictions with using delayed expansion, but unfortunately it has other limitations.
1) lines must be terminated by <CR><LF> (this will not be a problem if you do the TYPE file conversion)
2) lines must be <= 1021 bytes long (disregarding the <CR><LF>)
3) any trailing control characters are stripped from each line.
4) it must read from a file - you can't use a pipe. So in your case you will need to use a temp file to do your to ASCII conversion.
setlocal enableDelayedExpansion
type "file.txt">"file.txt.tmp"
for /f %%N in ('find /c /v "" ^<"file.txt.tmp"') do set cnt=%%N
<"file.txt.tmp" (
for /l %%N in (1 1 %cnt%) do(
set "ln="
set /p "ln="
echo(!ln!
)
)
del "file.txt.tmp"
I wrote a very simple program that may serve as replacement for FIND and FINDSTR commands when they are used for this purpose. My program is called PIPE.COM and it just insert a blank space in empty lines, so all the lines may be directly processed by FOR command with no further adjustments (as long as the inserted space don't cares). Here it is:
#ECHO off
if not exist pipe.com call :DefinePipe
FOR /F "USEBACKQ delims=" %%A IN (`pipe ^< "build.properties"`) DO (
ECHO(--%%A--
)
pause
goto :EOF
:DefinePipe
setlocal DisableDelayedExpansion
set pipe=´)€ì!Í!ŠÐŠà€Ä!€ü.t2€ü+u!:æu8²A€ê!´#€ì!Í!².€ê!´#€ì!Í!²+€ê!´#€ì!Í!Šò€Æ!´,€ì!Í!"Àu°´LÍ!ëÒ
setlocal EnableDelayedExpansion
echo !pipe!>pipe.com
exit /B
EDIT: Addendum as answer to new comment
The code at :DefinePipe subroutine create a 88 bytes program called pipe.com, that basically do a process equivalent to this pseudo-Batch code:
set "space= "
set line=
:nextChar
rem Read just ONE character
set /PC char=
if %char% neq %NewLine% (
rem Join new char to current line
set line=%line%%char%
) else (
rem End of line detected
if defined line (
rem Show current line
echo %line%
set line=
) else (
rem Empty line: change it by one space
echo %space%
)
)
goto nextChar
This way, empty lines in the input file are changed by lines with one space, so FOR /F command not longer omit they. This works "as long as the inserted space don't cares" as I said in my answer.
Note that the pipe.com program does not work in 64-bits Windows versions.
Antonio
Output lines including blank lines
Here's a method I developed for my own use.
Save the code as a batch file say, SHOWALL.BAT and pass the source file as a command line parameter.
Output can be redirected or piped.
#echo off
for /f "tokens=1,* delims=]" %%a in ('find /n /v "" ^< "%~1"') do echo.%%ba
exit /b
EXAMPLES:
showall source.txt
showall source.txt >destination.txt
showall source.txt | FIND "string"
An oddity is the inclusion of the '^<' (redirection) as opposed to just doing the following:
for /f "tokens=1,* delims=]" %%a in ('find /n /v "" "%~1"') do echo.%%ba
By omitting the redirection, a leading blank line is output.
Thanks to dbenham, this works, although it is slightly different than his suggestion:
::preserve blank lines using FIND, no limitations
for /f "USEBACKQ delims=" %%A in (`type "file.properties" ^| find /V /N ""`) do (
set "ln=%%A"
setlocal enableDelayedExpansion
set "ln=!ln:*]=!"
echo(!ln!
endlocal
)
As mentioned in this answer to the above question, it doesn't seem that lines are skipped by default using for /f in (at least) Windows XP (Community - Please update this answer by testing the below batch commands on your version & service pack of Windows).
EDIT: Per Jeb's comment below, it seems that the ping command, in at least Windows XP, is
causing for /f to produce <CR>'s instead of blank lines (If someone knows specifically why, would
appreciate it if they could update this answer or comment).
As a workaround, it seems that the second default delimited token (<space> / %%b in the example)
returns as blank, which worked for my situation of eliminating the blank lines by way of an "parent"
if conditional on the second token at the start of the for /f, like this:
for /f "tokens=1,2*" %%a in ('ping -n 1 google.com') do (
if not "x%%b"=="x" (
{do things with non-blank lines}
)
)
Using the below code:
#echo off
systeminfo | findstr /b /c:"OS Name" /c:"OS Version"
echo.&echo.
ping -n 1 google.com
echo.&echo.
for /f %%a in ('ping -n 1 google.com') do ( echo "%%a" )
echo.&echo.&echo --------------&echo.&echo.
find /?
echo.&echo.
for /f %%a in ('find /?') do ( echo "%%a" )
echo.&echo.
pause
.... the following is what I see on Windows XP, Windows 7 and Windows 2008, being the only three versions & service packs of Windows I have ready access to:

Windows Batch renaming from text document

I made a Batch script to rename a large amount of files. It takes their name and searches for it in a text document, copies the line and takes the data I need from it and then renames the file.
It seems to work fine for the most part, but I can't check to see how it's doing because it is constantly producing errors/warnings in the console.
#echo off
set ogg=.ogg
Setlocal EnableDelayedExpansion
for %%a in (*.ogg) do (
set fileNameFull=%%a
set fileName=!fileNameFull:~0,-4!
for /F "delims=" %%a in ('findstr /I !fileName! strings.txt') do (
endlocal
set "stringLine=%%a%ogg%"
)
Setlocal EnableDelayedExpansion
set fullString=!stringLine:~26!
ren %%a "!fullString!"
)
pause
The code works, I'd just like to be able to track progress, as 10,000s of files are being renamed at a time and I've no indication of how far along the process is.
The errors are:
"FINDSTR: Cannot open [...]"
"The syntax of the command is incorrect."
#echo off
Setlocal EnableDelayedExpansion
for %%a in (*.ogg) do (
for /F "delims=" %%q in ('findstr /I /L /c:"%%~na" strings.txt') do (
set "stringLine=%%q"
)
ECHO ren "%%a" "!stringLine:~26!.ogg"
)
pause
This code should be equivalent, but fixed, to the code you've posted.
Fixes:
Removed the endlocal/setlocal complication - not required
changed the inner `for` metavariable - must not be duplicate `%%a`
Changed the `findstr` switches - add `/L` for literal and `/c:` to force single token in case of a separator-in-name; use `%%~na` to specify "the name part of `%%a`" to avoid the substringing gymnastics.
removed said gymnastics
Removed 2-stage string manipulation of destination filename
Removed superfluous setting of `ogg`
The resultant code should duplicate what you have originally, except that it will simply report the rename instruction. You should test this against a small representative sample to verify.
for counting/progress:
set /a count=0
for %%a in (*.ogg) do (
for /F "delims=" %%q in ('findstr /I /L /c:"%%~na" strings.txt') do (
set "stringLine=%%q"
)
ECHO ren "%%a" "!stringLine:~26!.ogg"
set /a count +=1
set /a stringline= count %% 1000
if %stringline% equ 0 echo !count! Processed
)
pause
which should show you progress each 1000.
You could use
if %stringline% equ 0 echo !count! Processed&pause
to wait for user-action before progressing...
BTW -I'm making the assumption that the newname is from column 27+ in your file, since you've not shown us a sample.Also, you should be aware that a simple findstr would locate the target string as a substring anywhere within the file - either as the newname or the oldname. If you invoke the /B switch on the findstr, then the string will match at the very beginning of the line only.

identify or delete double quote char in batch script text stream or in a file

I have created command script for reading %N% lines from file. The problem is I can't delete " from anywhere in all text streams when I work with file's text. " deletion is very needed because if file's text line have substring like "text" and text have special chars or even worse, script code, then the script crashes or works not proper way (including script control capturing by programmer who specially composed the text).
If I can't delete " from the text stream(s), then I just want to identify, that the file (or it's first %N% lines, including empty lines) contains at least one " char.
Any thoughts are appreciated, including any file preprocessing. But main aim is script speed.
for /f "skip=2 delims=" %%a in ('find /v /n "" "file" 2^>nul') do set "v=%%a"&call :v&if not errorlevel 1 goto FURTHER1
goto FURTHER2
:v
for /f "delims=[]" %%a in ("%v%") do set "line%%a=%v:*]=%"&if %%a lss %N% (exit /b 1) else exit /b 0
#ECHO Off
SETLOCAL
SET "sourcedir=U:\sourcedir"
SET "filename1=%sourcedir%\q39558311.txt"
SET "tempfilename1=%sourcedir%\q39558311#.txt"
>"%tempfilename1%" ECHO("
SET /a linefound=0
FOR /f "tokens=1 delims=:" %%a IN ('findstr /n /g:"%tempfilename1%" "%filename1%"') DO (
IF %%a gtr 2 SET /a linefound=%%a&GOTO report
)
:report
ECHO quote found AT line %linefound%
DEL "%tempfilename1%"
GOTO :EOF
You would need to change the setting of sourcedir and filename1 to suit your circumstances.
tempfile1 can be any name - it's just a temporary file; I chose that particular name for convenience.
I used a file named q39558311.txt containing some dummy data for my testing.
Essentially, create a file containing a single quote on a single line *tempfile1) then use findstr with the /g:filename option to read in the target strings to find. When findstr finds the line, it numbers it and outputs line_number:line found. Using : as a delimiter, token 1 of this line is the line number.
I don't understand why you've used the skip=number in your code. Do you intend to skip testing the first 2 lines of the target file?
the IF %%a gtr 2 tests the line number found. If it is greater than 2, then the variable linefound is set and the for loop is terminated.
I chose to initialise linefound to zero. It will remain zero if no " is found in lines 2..end. Equally, you could clear it and then it will be defined (with a value of first-line-found-with-quote-greater than-2) and no defined on not found.
I can only identify ", but not delete. Waiting for your suggestions on it!
>nul 2>&1 findstr /m \" "file"
if not errorlevel 1 echo double quote found!

Resources