How to check the disk space of remote server through command prompt - windows

I have been running the following script in the cmd file to get the free disk space of remote servers.It returns size in byte, is there any way to get the size in MB or GB, ideally percentage would be good.
echo off
echo .
echo SERVER-1:
wmic /NODE:"SERVER-1" logicaldisk get size,freespace,caption
echo .
echo .
echo .
echo SERVER-2:
wmic /NODE:"TSERVER-2" logicaldisk get size,freespace,caption
echo .
pause

I would recommend PowerShell rather than wmic in cmd.exe. Short example:
Get-WmiObject Win32_LogicalDisk -ComputerName server-1,server-2 -Filter "DriveType=3" | Select-Object `
#{Name = "ComputerName"; Expression = {$_.__SERVER}},
DeviceID,
#{Name = "Size"; Expression = {$_.Size / 1GB}},
#{Name = "Free"; Expression = {$_.FreeSpace / 1GB}}
This produces output such as the following:
ComputerName DeviceID Size Free
------------ -------- ---- ----
server-1 C: 99.5097618103027 64.3940238952637
server-1 D: 199.873043060303 183.510925292969
server-2 C: 99.5097618103027 64.3940238952637
server-2 D: 199.873043060303 183.510925292969

Related

Saving results after a for loop in Windows CMD

I have been trying to create a line of code to ping a range of IP addresses, in the windows command prompt, and after it finishes save the results in a text file. I am using a for loop to do the pinging, but I can't figure out how to save the results in a text file.
This is what I am using:
for /l %i in (1,1,64) do #ping 10.39.63.%i -w 1500 -n 1 | find "Reply"
I tried using the following code to save results in a text file, but it only saves the last command performed by CMD:
for /l %i in (1,1,64) do #ping 10.39.63.%i -w 100 -n 1 | find "Reply" >C:\Users\brymed\Desktop\test.txt
I want to keep it simple, so it'd be awesome to use only a line of code, but I am open to suggestions. Thank you.
This is not difficult using PowerShell. The $Hosts variable is a list of IP addresses to ping. The results are written to a file.
$Hosts = #()
foreach ($i in 1..64) { $Hosts += "10.39.63.$i" }
Test-Connection -Count 1 $hosts |
Select-Object -Property Address,BufferSize,Latency,Status |
Out-File -FilePath "$Env:USERPROFILE/Desktop/test.txt" -Encoding ascii
If you -must- run this in cmd.exe, the code can be formatted to do so.
pwsh.exe -NoLogo -NoProfile -Command ^
"$Hosts = #();" ^
"foreach ($i in 1..64) { $Hosts += \"10.39.63.$i\" };" ^
"Test-Connection -Count 1 $hosts -ErrorAction SilentlyContinue |" ^
"Select-Object -Property Address,BufferSize,Latency,Status |" ^
"Out-File -FilePath "$Env:USERPROFILE/Desktop/test.txt" -Encoding ascii"
Get PowerShell Core from https://github.com/PowerShell/PowerShell

How to combine two commands to get one output using command prompt

I have a folder on a shared network drive with a large number of text files. I am required to list the file name, size and number of lines/ rows in each file. I am able to use command prompt to get the output separately but I cannot seem to combine.
This works perfectly to list the file name and size:
DIR /s “files location*.txt” > Directory.txt
This works to for the line count:
for %f in ("files location*.txt" ) do find /v /c "" "%f"
I tried the following to combine but the output was empty and the command prompt window showed the full file location and name but without the line count
DIR /s “files location*.txt” | for %f in (“files location*.txt”) do find /v /c "" "%f" > Directory.txt
I think this question has been here before. Put these two (2) files into the same directory. The directory should be in the PATH variable. Many things could be done to make this more flexible using parameters. If you are on a supported Windows system, PowerShell will be available. If you have PowerShell 6 or higher, change powershell to pwsh.
=== Get-FileLineCount.bat
#ECHO OFF
powershell -NoLogo -NoProfile -File "%~dp0Get-FileListCount.ps1"
EXIT /B
=== Get-FileLineCount.ps1
Get-ChildItem -File -Path 'C:\src\t' -Filter '*.txt' |
ForEach-Object {
[PSCustomObject]#{
LastWriteTime = $_.LastWriteTime
Length = $_.Length
LineCount = (Get-Content -Path $_.FullName | Measure-Object).Count
FileName = $_.FullName
}
}
This produces the following output.
LastWriteTime Length LineCount FileName
------------- ------ --------- --------
2021-04-08 08:14:59 3 1 C:\src\t\abc.txt
2021-04-08 08:16:39 8 1 C:\src\t\abc-utf-8.txt
2019-07-08 11:38:36 30 1 C:\src\t\append.txt
2019-07-08 11:38:36 36 12 C:\src\t\appendtemp.txt
2020-03-06 09:48:51 104 25 C:\src\t\Combined.txt

Getting Hardware Info script trouble

With help from the Internet I've managed to write a basic PowerShell script that collects hardware info and exports it to a CSV file. It gathers:
Hostname
CPU
NumberOfCores
GPU
RAM
My script still needs to get HDD info (capacity, freespace, id), IPv4 address and MAC.
$Name = hostname
$Motherboard = Get-WmiObject Win32_BaseBoard
$CPU = Get-WmiObject Win32_Processor
$GPU = Get-WmiObject Win32_VideoController
$RAM = Get-WmiObject Win32_ComputerSystem
$To_File = new-object PSObject -property #{
'Name' = $Name
'Motherboard' = $Motherboard.Product
'CPU' = $CPU.Name
'Cores' = $CPU.NumberOfCores
'GPU' = $GPU.Name
'RAM' = "{0:N2}" -f ($RAM.TotalPhysicalMemory/1GB)
}
$To_File | Select-Object Name, Motherboard, CPU, Cores, GPU, RAM |
Export-Csv G:\$Name.csv
Earlier, I also had a line for getting IP and MAC, but it wasn't working universally. It looked like this:
$IP = gwmi Win32_NetworkAdapterConfiguration | Where ($_.DNSDomain -eq 'lan')
$MAC = gwmi Win32_NetworkAdapterConfiguration | Where ($_.DNSDomain -eq 'lan')
Then I would just use in $To_File object 'IP' = $IP.IPAddress and 'MAC' = $MAC.MacAddress
It wasn't good since not all the adapters were named "lan".
For HDD I wrote:
$Disk = Get-WmiObject Win32_LogicalDisk -Filter drivetype=3
$DiskInfo = foreach ($zm in $Disk) {
'ID: ' + $zm.DeviceID
'Capacity: ' + "{0:N2}" -f ($zm.Size/1GB)
'Free Space: ' + "{0:N2}" -f ($zm.FreeSpace/1GB)
}
Since some computers had more than one HDD but I didn't know how I can join these two things together so I could have all that info above and HDD's in one file.
I can't do all that stuff remotely, so the script is on a USB drive and I go to each computer and run it by myself. I still have to do around 20 machines.
I'd also like to know how I can add new rows to an existing CSV file because having 15 CSVs and 'merging' them together is painfull.
Use the -append command with your export-csv command in order add new rows with the existing rows. Your command would look like
$To_File | Select-Object Name, Motherboard, CPU, Cores, GPU, RAM |
Export-Csv G:\$Name.csv -NoTypeInformation -Append
Powershell - Export-CSV and Append link will be helpful to you I guess.

Get length of the longest file path in a folder and its sub folders

I'm looking for a script that can be run from command line (batch \ PowerShell) that will go over a folder and its sub folders and will return a number which is a length of the longest file path.
I already saw some batch and PowerShell scripts like
How do I find files with a path length greater than 260 characters in Windows?
but none of them works satisfy my request.
Note that it's possible that file path will be more than 256 characters
PowerShell:
((Get-ChildItem -Recurse).FullName | Measure-Object -Property Length -Maximum).Maximum
Command line:
powershell -exec Bypass -c "((dir -rec).FullName | measure Length -max).Maximum"
Edit
related to error: Get-ChildItem : The specified path, file name, or both are too long: read Maximum Path Length Limitation and related [PowerShell]-tagged StackOverflow threads.
PS D:\PShell> ((Get-ChildItem "D:\odds and ends" -Directory -Recurse).FullName | Measure-Object -Property Length -Maximum).Maximum
242
PS D:\PShell> ((Get-ChildItem "D:\odds and ends" -Recurse -ErrorAction SilentlyContinue).FullName | Measure-Object -Property Length -Maximum).Maximum
242
Note that -ErrorAction SilentlyContinue in above command merely suppresses displaying of error messages. However, I know that the latter 242 value returned is wrong.
My workaroud applies cmd /C dir /B /S instead of (Get-ChildItem -Recurse).FullName as follows:
PS D:\PShell> $x = (. cmd /C dir /B /S "D:\odds and ends")
PS D:\PShell> $y = ( $x | Measure-Object -Property Length -Maximum).Maximum
PS D:\PShell> $y
273
PS D:\PShell> $z = $x | Where-Object { $_.Length -gt 260 }
PS D:\PShell> $z.GetTypeCode()
String
PS D:\PShell> $z
D:\odds and ends\ZalohaGogen\WDElements\zalohaeva\zaloha_honza\Music\Jazz\!Kompilace\Saint Germain des Pres Cafe Vol. 1 to 8 - The Finest Electro Jazz Complication\Saint Germain Des Pres Cafe Vol. 7 - The Finest Electro Jazz Complication\CD 1\Configuring and Using Inte.txt
PS D:\PShell>

get IPv4 address into a variable

Is there an easy way in PowerShell 3.0 on Windows 7 to get the local computer's IPv4 address into a variable?
Here is another solution:
$env:HostIP = (
Get-NetIPConfiguration |
Where-Object {
$_.IPv4DefaultGateway -ne $null -and
$_.NetAdapter.Status -ne "Disconnected"
}
).IPv4Address.IPAddress
How about this? (not my real IP Address!)
PS C:\> $ipV4 = Test-Connection -ComputerName (hostname) -Count 1 | Select IPV4Address
PS C:\> $ipV4
IPV4Address
-----------
192.0.2.0
Note that using localhost would just return and IP of 127.0.0.1
PS C:\> $ipV4 = Test-Connection -ComputerName localhost -Count 1 | Select IPV4Address
PS C:\> $ipV4
IPV4Address
-----------
127.0.0.1
The IP Address object has to be expanded out to get the address string
PS C:\> $ipV4 = Test-Connection -ComputerName (hostname) -Count 1 | Select -ExpandProperty IPV4Address
PS C:\> $ipV4
Address : 556228818
AddressFamily : InterNetwork
ScopeId :
IsIPv6Multicast : False
IsIPv6LinkLocal : False
IsIPv6SiteLocal : False
IsIPv6Teredo : False
IsIPv4MappedToIPv6 : False
IPAddressToString : 192.0.2.0
PS C:\> $ipV4.IPAddressToString
192.0.2.0
If I use the machine name this works. But is kind of like a hack (because I am just picking the first value of ipv4 address that I get.)
$ipaddress=([System.Net.DNS]::GetHostAddresses('PasteMachineNameHere')|Where-Object {$_.AddressFamily -eq "InterNetwork"} | select-object IPAddressToString)[0].IPAddressToString
Note that you have to replace the value PasteMachineNameHere in the above expression
This works too
$localIpAddress=((ipconfig | findstr [0-9].\.)[0]).Split()[-1]
Here are three methods using windows powershell and/or powershell core, listed from fastest to slowest.
You can assign it to a variable of your choosing.
Method 1: (this method is the fastest and works in both windows powershell and powershell core)
$ipAddress = (Get-NetIPAddress | Where-Object {$_.AddressState -eq "Preferred" -and $_.ValidLifetime -lt "24:00:00"}).IPAddress
Method 2: (this method is as fast as method 1 but it does not work with powershell core)
$ipAddress = (Test-Connection -ComputerName (hostname) -Count 1 | Select -ExpandProperty IPv4Address).IPAddressToString
Method 3: (although the slowest, it works on both windows powershell and powershell core)
$ipAddress = (Get-NetIPConfiguration | Where-Object {$_.IPv4DefaultGateway -ne $null -and $_.NetAdapter.status -ne "Disconnected"}).IPv4Address.IPAddress
Here is what I ended up using
$ipaddress = $(ipconfig | where {$_ -match 'IPv4.+\s(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' } | out-null; $Matches[1])
which breaks down as
execute ipconfig command - get all the network interface information
use powershell's where filter with a regular expression
regular expression finds the line with "IPv4" and a set of 4 blocks each with 1-3 digits separated by periods, i.e. a v4 IP address
disregard the output by piping it to null
finally get the first matched group as defined by the brackets in the regular expression.
catch that output in $ipaddress for later use.
(Get-WmiObject -Class Win32_NetworkAdapterConfiguration | where {$_.DHCPEnabled -ne $null -and $_.DefaultIPGateway -ne $null}).IPAddress
This one liner gives you the IP address:
(Test-Connection -ComputerName $env:computername -count 1).ipv4address.IPAddressToString
Include it in a Variable?
$IPV4=(Test-Connection -ComputerName $env:computername -count 1).ipv4address.IPAddressToString
Another variant using $env environment variable to grab hostname:
Test-Connection -ComputerName $env:computername -count 1 | Select-Object IPV4Address
or if you just want the IP address returned without the property header
(Test-Connection -ComputerName $env:computername -count 1).IPV4Address.ipaddressTOstring
tldr;
I used this command to get the ip address of my Ethernet network adapter into a variable called IP.
for /f "tokens=3 delims=: " %i in ('netsh interface ip show config name^="Ethernet" ^| findstr "IP Address"') do set IP=%i
For those who are curious to know what all that means, read on
Most commands using ipconfig for example just print out all your IP addresses and I needed a specific one which in my case was for my Ethernet network adapter.
You can see your list of network adapters by using the netsh interface ipv4 show interfaces command. Most people need Wi-Fi or Ethernet.
You'll see a table like so in the output to the command prompt:
Idx Met MTU State Name
--- ---------- ---------- ------------ ---------------------------
1 75 4294967295 connected Loopback Pseudo-Interface 1
15 25 1500 connected Ethernet
17 5000 1500 connected vEthernet (Default Switch)
32 15 1500 connected vEthernet (DockerNAT)
In the name column you should find the network adapter you want (i.e. Ethernet, Wi-Fi etc.).
As mentioned, I was interested in Ethernet in my case.
To get the IP for that adapter we can use the netsh command:
netsh interface ip show config name="Ethernet"
This gives us this output:
Configuration for interface "Ethernet"
DHCP enabled: Yes
IP Address: 169.252.27.59
Subnet Prefix: 169.252.0.0/16 (mask 255.255.0.0)
InterfaceMetric: 25
DNS servers configured through DHCP: None
Register with which suffix: Primary only
WINS servers configured through DHCP: None
(I faked the actual IP number above for security reasons 😉)
I can further specify which line I want using the findstr command in the ms-dos command prompt.
Here I want the line containing the string IP Address.
netsh interface ip show config name="Ethernet" | findstr "IP Address"
This gives the following output:
IP Address: 169.252.27.59
I can then use the for command that allows me to parse files (or multiline strings in this case) and split out the strings' contents based on a delimiter and the item number that I'm interested in.
Note that I am looking for the third item (tokens=3) and that I am using the space character and : as my delimiters (delims=: ).
for /f "tokens=3 delims=: " %i in ('netsh interface ip show config name^="Ethernet" ^| findstr "IP Address"') do set IP=%i
Each value or token in the loop is printed off as the variable %i but I'm only interested in the third "token" or item (hence tokens=3). Note that I had to escape the | and = using a ^
At the end of the for command you can specify a command to run with the content that is returned. In this case I am using set to assign the value to an environment variable called IP. If you want you could also just echo the value or what ever you like.
With that you get an environment variable with the IP Address of your preferred network adapter assigned to an environment variable. Pretty neat, huh?
If you have any ideas for improving please leave a comment.
I was looking for the same thing and figured this out:
$ip = Get-NetIPAddress -AddressFamily IPv4 -InterfaceIndex $(Get-NetConnectionProfile | Select-Object -ExpandProperty InterfaceIndex) | Select-Object -ExpandProperty IPAddress
This filters out both the loopback address and some virtual networks I have.
$ip = (Get-NetIPAddress -AddressFamily IPv4 -InterfaceIndex $(Get-NetConnectionProfile).InterfaceIndex).IPAddress
OR
function Get-LocalIP {
(
Get-NetIPAddress `
-AddressFamily IPv4 `
-InterfaceIndex $(
Get-NetConnectionProfile
).InterfaceIndex
).IPAddress
}
$ip = Get-LocalIP
To grab the device's IPv4 addresses, and filter to only grab ones that match your scheme (i.e. Ignore and APIPA addresses or the LocalHost address). You could say to grab the address matching 192.168.200.* for example.
$IPv4Addr = Get-NetIPAddress -AddressFamily ipV4 | where {$_.IPAddress -like X.X.X.X} | Select IPAddress
# Patrick Burwell's Ping Script - Patrick.Burwell#Infosys.com #
$Output= #() #sets an array
$names = Get-Content ".\input\ptd.pc_list.txt" #sets a list to use, like a DNS dump
foreach ($name in $names){ #sets the input by enumerating a text file to loop through and sets a variable to execute against
if ($IPV4 = Test-Connection -Delay 15 -ComputerName $name -Count 1 -ErrorAction SilentlyContinue|select IPV4Address #run ping and sets only IPV4Address response variable
){# If true then run...
$Output+= $Name,($IPV4.IPV4Address).IPAddressToString # Fills the array with the #true response
Write-Host $Name',','Ping,'($IPV4.IPV4Address).IPAddressToString -ForegroundColor Green #Sets the output to receive the Name, result and IPV4Address and prints the reply to the console with specific colors
}
else{#If false then run...
$Output+= "$name," #Fills the array with the #false response
Write-Host "$Name," -ForegroundColor Red #Prints the reply to the console with specific colors
}
}
#$Output | Out-file ".\output\result.csv" #<-- use to export to a text file (Set path as needed)
#$Output | Export-CSV ".\output\result.csv" -NoTypeInformation #<-- use to export to a csv file (Set path as needed)
#If you choose, you can merely have the reply by the name and IP, and the Name and no IP by removing the Ping comments
As I was working in Powershell 3, none of the answers here worked for me. It's based on Rob's approach, but this one works when you have multiple network adapters, it also picks out the IP correctly using capture groups
function GetIPConfig {
return ipconfig | select-string ('(\s)+IPv4.+\s(?<IP>(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}))(\s)*') -AllMatches | %{ $_.Matches } | % { $_.Groups["IP"]} | %{ $_.Value }
}
Non of the top comments are actually fully correct since a computer can have multiple interfaces and an interface can have multiple IP addresses. There are a few answers here which technically correct but utilizes "funky" ways to filter out wellknown addresses (like APIPA, localhost, etc) whereas even Powershell 3.0 have a native way to do so with PrefixOrigin.
$IPv4Addresses = $(Get-NetIPAddress | Where-Object { $_.PrefixOrigin -ne "WellKnown" -and $_.AddressFamily -eq "IPv4" }).IPAddress
I do this :
$interFaceAliasName="LAN" # You have to change the name according to your interface's name
$myInterface=(Get-NetIPAddress -InterfaceAlias $interFaceAliasName)
$myIP=$myInterface.IPv4Address
I recently had the same issue. So I wrote a script to parse it from the ipconfig /all output. This script is easily modifiable to obtain any of the parameters of the interfaces and it works on Windows 7 also.
Get output of IP config in LineNumber | Line format
$ip_config = $(ipconfig /all | % {$_ -split "rn"} | Select-String -Pattern ".*" | select LineNumber, Line)
Get list of interfaces (+ last line of ipconfig output) in LineNumber | Line format
$interfaces = $($ip_config | where {$_.Line -notmatch '^\s*$'} | where {$_.Line -notmatch '^\s'}) + $($ip_config | Select -last 1)
Filter through the interfaces list for the specific interface you want
$LAN = $($interfaces | where {$_.Line -match 'Wireless Network Connection:$'})
Get the start and end line numbers of chosen interface from output
$i = $interfaces.IndexOf($LAN)
$start = $LAN.LineNumber
$end = $interfaces[$i+1].LineNumber
Pick the lines from start..end
$LAN = $ip_config | where {$_.LineNumber -in ($start..$end)}
Get IP(v4) address field (returns null if no IPv4 address present)
$LAN_IP = #($LAN | where {$_ -match 'IPv4.+:\s(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'})
$LAN_IP = &{If ($LAN_IP.Count -gt 0) {$Matches[1]} Else {$null}}
$a = ipconfig
$result = $a[8] -replace "IPv4 Address. . . . . . . . . . . :",""
Also check which index of ipconfig has the IPv4 Address

Resources