Get command prompt out on one line - cmd

I am trying to get Model and Size of all local disks.
I want to output on one line for each disk.
Example: Model Samsung Size 500GB
#echo off
for /f "tokens=2 delims==" %%d in ('wmic diskdrive get Model,Size /value') do (
set Model=%%d
set Size=%%d
)
echo Model %Model% Size %Size%
pause
But nothing.

As model descriptions may contain spaces, you need to format the output as csv, so the output is delimited by commas (I hope there aren't model descriptions that contain commas - I didn't see one so far).
Without /value each disk is listed in one line (Node,Model,Size), so you need tokens=2,3. Add a skip=2 to remove the header line and add your fixed strings to the final output:
for /f "skip=2 tokens=2,3 delims=," %%a in ('"wmic diskdrive get Model,Size /format:csv"') do #echo Model %%a Size %%b

Here is one way to do it on all current day, supported Windows machines. The stated goal is "one line." If you want model and size in separate variables, there is more to do.
powershell -NoLogo -NoProfile -Command ^
"Get-CimInstance -ClassName CIM_DiskDrive |" ^
"ForEach-Object { 'Model {0} Size {1}' -f #($_.Model, $_.size) }"

Related

Adding a comma at the end of each line wmic

I am trying to get a comma seperated list of printers my computer has access to. So far I have #echo off & for /f "delims=" %i in ('wmic printer get name ^| findstr /v "Name"') do echo %i, but for some reason it's replacing the first letter of each printer with a comma. Changing the %i, in the end is slightly better, not replacing the first letter with a comma but just adding one in front of the name of the printer instead. Though this is better this is not what I'm looking for because I want to get the output.
PrinterOne,
Printer2,
Printer3,
etc,
I'm pretty sure %i, should work, or am I wrong?
Side note I've had a working solution for months running
For /F "Tokens=1,* EOL=' Delims=," %%G In ('%%SystemRoot%%\System32\wbem\WMIC.exe Printer Get Name^ /Format:CSV 2^>NUL') Do #For /F "Tokens=*" %%I In ("%%H") Do #Echo %%I,
from a batch file, but as it looks it does not work with some of the computers on our system. Could be windows related but I'm not sure.
I managed this with
powershell -Command "& { Get-Printer -ComputerName $env:COMPUTERNAME | Select-Object -ExpandProperty Name | foreach-object {$_ + ','}}"

Take username and Products on batch file

Can I take the username and list products installed in the same txt file?
I thought of something like:
for /f "usebackq tokens=* delims=" %%a in (`wmic product get name`) do (
set "result=%%a"
)
echo %username%/%result% > test.txt
But no success.
I need this to put this on an Excel file, with another program, and I need this structure, username/programs.
(
for /f "usebackq tokens=* delims=" %%a in (`wmic product get name`) do (
echo %username%/%%a
)
)> test.txt
You can absolutely do that, you just need to keep in mind that for loops process one line at a time, so you need to output the value while you're still in the loop.
for /f "delims=" %%A in ('wmic product get name') do (
echo %%A >>test.txt
)
You don't need to set a variable for this since you aren't doing any string manipulation with it, but if you did, you would have to use delayed expansion:
#echo off
setlocal enabledelayedexpansion
for /f "delims=" %%A in ('wmic product get name') do (
set "line=%%A"
echo !line! >>test.txt
)
You can also skip the for loop altogether and just redirect the output of the wmic command straight to the text file:
wmic product get name >>test.txt
You could probably use powershell from cmd or your batch-file, to get this information as a single line in CSV file in the format:
"UserName","Program Name 1","Program Name 2", "Program Name 3", etc…
Example command:
%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoLogo -NoProfile -Command "'\"' + (#($([System.Security.Principal.WindowsIdentity]::GetCurrent().Name.Split('\\')[-1])) + (Get-CimInstance -Class Win32_Product -Filter 'Name Is Not Null').Name -Join '\",\"') + '\"'" 1> "UserProducts.csv"

I need a windows command line script that takes an output, edits it and creates an environmental variable

I have Asset tags embedded in BIOS. I use
wmic SYSTEMENCLOSURE get SMBiosAssetTag
This pulls the information I want but it is not formatted well:
SMBIOSAssetTag
11886
I need to just have those 5 numbers and nothing else. I will then use that variable to name the computer with a first logon script. I have spent hours on this, and I could have been done in 3 minutes if this was linux.
Note: I can't put linux tools on these builds :-(
Using
WMIC SYSTEMENCLOSURE GET SMBiosAssetTag /FORMAT:VALUE
will make a better output:
(some empty lines)
SMBIOSAssetTag=CZC1296FLD
(some empty lines)
So, in batch you may just
FOR /F "TOKENS=1,* DELIMS==" %%v IN (WMIC SYSTEMENCLOSURE GET SMBiosAssetTag /FORMAT:VALUE) DO IF /I "%%v" == "SMBIOSAssetTag" SET SMBIOSAssetTag=%%w
Side note: hard part in WMIC output is handling empty lines.
This will work, tested it myself:
for /f "eol=S" %%a in ('wmic SYSTEMENCLOSURE get SMBiosAssetTag^|sort') do (set var=%%a)
It works fine.
Mona
for /f "delims=" %%a in ('wmic SYSTEMENCLOSURE get SMBiosAssetTag') do for /f %%b in ("%%a") do set "var=%%b"
echo %var%

Can a wmic processes table (within the command prompt window) be sorted by a value?

I've been exploring various options, such as the /format flag, however it appears that sorting is only possible in XML or HTML output. I would like to sort within command prompt itself. It seems that even TaskList cannot do this (and I would prefer to use wmic since it seems to perform faster).
An example of a command to run would be wmic process get name,processid,workingsetsize. Processes appear to be sorted by processid, but it would make much more sense (in my use case, at least) to sort by name or memory usage (workingsetsize).
As requested, here's an example wmic process table output:
Name ProcessId WorkingSetSize
System Idle Process 0 20480
System 4 765952
smss.exe 384 393216
csrss.exe 500 2850816
wininit.exe 596 774144
csrss.exe 612 6230016
winlogon.exe 672 2023424
services.exe 696 7192576
lsass.exe 704 9814016
svchost.exe 820 5287936
svchost.exe 872 7454720
atiesrxx.exe 936 1028096
Obviously, process lists can get very long, so I've cut it off there.
#ECHO OFF
SETLOCAL
FOR /f "delims==" %%i IN ('set $ 2^>nul') DO SET "%%i="
FOR /f "delims=" %%i IN ('wmic process get Name^, ProcessId^, WorkingSetSize ') DO (
IF DEFINED $0 (
SET wss=%%i
CALL SET wss=0000000000000000000%%wss:~60%%
CALL SET wss=%%wss: =%%
CALL SET wss=$%%wss:~-20%%
CALL SET %%wss%%=%%i
) ELSE (SET $0=%%i)
)
FOR /f "tokens=1*delims==" %%i IN ('set $') DO ECHO(%%j
This should do your sort.
The sticking points are: the WMIC command requires commas between fieldnames. These need to be escaped in the for/f
All environment variables starting "$" are first deleted, then each line of WMIC is processed. The first line (the header) is saved in $0 then each line is saved in $size
The trick here is that SIZE in the listing is not only left-justified by space-padded, hence the string of zeroes is first prefixed to the contents of the workingsetsize column which probably actually begins in column 62 - but column 61 is a space. "60" is used since the substring facility counts from column 0, not column 1.
Then each space is replaced by [nothing], stripping out the trailing spaces (also conveniently, the space from col 61)
The last 20 characters from the resultant string form a leading-zero-filled version of the workingsetsize column.
prepend a $ to tha, and set the resultant variable to the contents of the line that generated it
Finally, listing the contents of the $ variables produces the required list in the required order.
Note that the claims that the WMIC process output described is in order whatever is erroneous. Closer examination would reveal that it is not in order of ProcessID - either alphabetically (since that column is also left-justified) or alphabetically.
OK - revised version, should auto-adjust to width of process-name column:
#ECHO OFF
SETLOCAL
FOR /f "delims==" %%i IN ('set $ 2^>nul') DO SET "%%i="
SET /A COUNT=0
FOR /f "delims=" %%i IN ('wmic process get Name^, ProcessId^, WorkingSetSize ') DO (
IF DEFINED $0 (
SET wss=%%i
CALL %%lopcmd%%
CALL SET wss2=%%wss2: =%%
SET /A COUNT+=1
CALL SET wss=$%%wss2:~-20%%%%COUNT%%
CALL SET %%wss%%=%%i
) ELSE (SET $0=%%i&set/a wsscol=0&CALL :findcol&SET $0=%%i)
)
FOR /f "tokens=1*delims==" %%i IN ('set $') DO ECHO(%%j
GOTO :eof
:findcol
IF "%$0:~0,1%"=="W" SET lopcmd=CALL SET wss2=0000000000000000000%%wss:~%wsscol%%%&GOTO :eof
SET $0=%$0:~1%
SET /a wsscol+=1
GOTO findcol
No substantial changes - just calculate the width required by locating the "W" in the header and establishing an appropriate command to set the variable ready for processing...and which has to executed using the CALL %%var%% method...
Minor edit: introducing COUNT to distinguish between lines with identical workingsetsizes. Count is simply extends the variable-name used for sorting and makes the name unique.
Is this any use to you? It works in Win 8 to provide a list of processes sorted by memory usage.
tasklist /nh |sort /+65
This might work on the command line (depends on Windows version, without any warranty!):
(for /f "delims=" %i in ('wmic process get Name^, ProcessId^, WorkingSetSize ') do #set "wss=%i" &call set "wss=%wss:~0,35%%wss:~-12%"&call echo(%wss%) | more +1 | sort /+35
I understand your question and this works just fine for me on Windows 10:
wmic process list get name, version |sort
or
wmic process list status |sort
or
wmic process list io |sort
Expounding upon Foxidrive's answer, this works with tasklist also:
tasklist /nh | sort
and no need for the /+65 (thanks for that info foxidrive)
"tasklist" on Windows 10 will do this also:
tasklist /nh /fo table
or
tasklist /fo list
or
tasklist /nh |sort
I used Peter's technique here but returned the data in CSV format, which is easier to parse for a batch file in "PID, WorkingSetSize, Name" format sorted on the size column.
#ECHO OFF
SETLOCAL
FOR /f "delims==" %%i IN ('set $ 2^>nul') DO SET "%%i="
FOR /f "skip=2 tokens=2-4 delims=," %%a IN ('cmd /c "wmic process get Name, ProcessId, WorkingSetSize /format:csv" ') DO (
SET wss=0000000000000000000%%c
CALL SET $%%wss:~-20%%=%%b,%%c,%%a
)
FOR /f "tokens=1*delims==" %%i IN ('set $') DO ECHO(%%j
pause
If PowerShell is an option for you then the following should work:
PS C:\> Get-CimInstance -query "select * from win32_process" | Sort-Object -Property Name | Format-Table -Property Name, ProcessId, WorkingSetSize

Why is the FOR /f loop in this batch script evaluating a blank line?

I'm trying to write a batch script that obtains (among other things) a list of all of the disk drives the computer has. The basic code looks something like this:
REM Build the list of disk drives to monitor
SETLOCAL enabledelayedexpansion
FOR /f "skip=1 tokens=1 delims=:" %%a in ('"WMIC logicaldisk WHERE drivetype=3 GET deviceid"') do (
SET "DISK_DATABASES=!DISK_DATABASES!%%a|"
SET "DRIVES_TO_MONITOR=!DRIVES_TO_MONITOR!%%a:\\|"
)
I pretty obviously build two lists with slightly different formats for use later. When I run this, however, the output I get looks something like this:
C|D|E||
C:\\|D:\\|E:\\|:\\|
Now, I expect the trailing pipe in both cases and I can manage that, but I'm really confused why there is an extra blank entry in there. If I run the wmic command manually, I can see that there is indeed a blank line at the end of the output, but my understanding is that /f was specifically supposed to ignore blank lines.
If I turn ECHO on, it looks like that last line is just coming in as a carriage return/newline or similar. Is there a way to do what I'm expecting? Am I missing something? I tried to write an if condition in the loop to exclude this last line, but it was... funky and never worked. I appreciate any/all help.
I just came over this topic. I've been using findstr /v to exclude empty lines:
FOR /f "usebackq skip=1 tokens=1 delims=:" %%a in (`WMIC logicaldisk WHERE "drivetype=3" GET deviceid ^| findstr /v /r "^$"`) do (
In this case the last iteration produces not an empty item, and you get your output of C|D|E|| only with echo %DISK_DATABASES%,
but echo !DISK_DATABASES! will output ||D|E|??
That's because the last element is a single <CR> character.
And <CR> characters are directly removed after the percent expansion, but not with delayed expansion.
You could avoid this, using the percent expansion to remove them
setlocal EnableDelayedExpansion
FOR /f "skip=1 tokens=1 delims=:" %%a in ('"WMIC logicaldisk WHERE drivetype=3 GET deviceid"') do (
set "item=%%a"
call :removeCR
if not "!item!"=="" (
SET "DISK_DATABASES=!DISK_DATABASES!!item!|"
SET "DRIVES_TO_MONITOR=!DRIVES_TO_MONITOR!!item!:\\|"
)
)
goto :eof
:removeCR
:removeCR
set "Item=%Item%"
exit /b
According to http://ss64.com/nt/for_f.html
Many of the newer commands and utilities (e.g. WMIC) output text files in unicode format, these cannot be read by the FOR command which expects ASCII.
To convert the file format use the TYPE command.
So it appears that WMIC and FOR don't play nice together.
I discovered a more efficient and more reliable method to strip the unwanted <CR> from the end of each line. No temp file, and no CALL needed.
I don't understand the mechanism of how FOR /F converts the WMIC unicode output into ASCII. Normally FOR /F cannot read unicode. But however it works, each converted line ends with <CR><CR><LF>. FOR /F breaks lines at each <LF>, and then if the last character in the line is <CR> it strips that last <CR>, in this case leaving behind the unwanted <CR>.
The solution is to simply pass each line through one more FOR /F :-)
#echo off
setlocal enableDelayedExpansion
for /f "skip=1 delims=" %%A in (
'wmic logicaldisk where "drivetype=3" get deviceid'
) do for /f "tokens=1 delims=:" %%B in ("%%A") do (
set "disk_databases=!disk_databases!%%B|"
set "drives_to_monitor=!drives_to_monitor!%%B:\\|"
)
This method is more reliable then using normal expansion because you don't have to worry about quoting or escaping special characters. For example, The CALL method that uses normal expansion cannot handle a string like "this & that" & the other. But this method has no problem with such a string.
Add ^| findstr . and you will get only not blank lines
REM Build the list of disk drives to monitor
SETLOCAL enabledelayedexpansion
FOR /f "skip=1 tokens=1 delims=:" %%a in (
'"WMIC logicaldisk WHERE drivetype=3 GET deviceid" ^| findstr .') do (
SET "DISK_DATABASES=!DISK_DATABASES!%%a|"
SET "DRIVES_TO_MONITOR=!DRIVES_TO_MONITOR!%%a:\|"
)
My standard idiom for dealing with this is to write the output from WMIC to a temp file, then use TYPE (which reduces UTF16 to ASCII) to feed that into FOR, like this:
:: Standard environment setup
setlocal enabledelayedexpansion
:: Every variable whose name starts with "tf" will identify a temporary
:: file - remove any such variables inherited from the parent environment
for /f %%V in ('set tf') do set %%V=
:: Create some temporary filenames. Prefix all of them with this script's
:: own name to avoid clashes with those owned by other scripts.
for /l %%I in (1,1,4) set tf%%I="%temp%\%~n0-temp%%I.txt"
:: Use temp file to work around coding mismatch between WMIC out and FOR in
wmic product where "name like 'Microsoft Office %% 2010'" get packagecache >!tf1!
for /f "skip=1" %%P in ('type !tf1!') do if exist "%%~P" msiexec /x "%%~P" /passive /norestart
:: Before quitting script, clean up temporary files
for /f %%V in ('set tf') do if exist "%%~V" del /f /q "%%~V"
endlocal
Run the following command:
wmic blah /value | find "=" >> wherever
Output will be:
field=value
Note that there will be no extra lines.

Resources