Windows/Scripting
PowerShell
Check version and update as needed:
PS C:\Users\bob> $PSVersionTable PSVersion 5.1.22000.2003 PSEdition Desktop
After PowerShell is started, find out where our profile[1] is stored, as this varies[2] between Windows versions:
% powershell PS C:\temp> $profile C:\Users\bob\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
We can now create scripts in Microsoft.PowerShell_profile.ps1
that will get loaded the next time PowerShell starts. E.g., setting a prompt[3] or defining functions:[4]
function prompt { "PS " + $(get-location) + "> " } function sudo { Start-Process @args -verb runas }
Before we can use that script, we need to alter our execution policy for PowerShell scripts:
$ Get-ExecutionPolicy RemoteSigned $ Set-ExecutionPolicy RemoteSigned
With that, the locally stored Microsoft.PowerShell_profile.ps1
will now be used. Reload on the fly via . $PROFILE
.
Core commands
Let's grep
for strings:
$ gci env: | findstr "^OS" OS Windows_NT
Use tail
to follow a file:
Get-Content file.log -Wait Get-Content file.log -Wait -Tail 10 # print the last 10 lines, then follow (PowerShell 3 only)
Search for something while running tail
:
Get-Content file.log -wait | where { $_ -match "foo" }
Use head
in combination with sort
:
$ gci env:* | Select -first 3 | Sort-Object name LOGONSERVER \\example USERNAME bob USERPROFILE C:\Users\bob
A very simple netcat
substitute, for UDP and TCP:
(New-Object Net.Sockets.UdpClient).Connect("some-host",1234) (New-Object Net.Sockets.TcpClient).Connect("some-host",1234)
rename
Based on an overcomplicated workflow, we had the following problem to solve: rename PDF files based on their file content. In lieu of awk
,[5][6] we used a few lines of PowerShell (courtesy of someone else) and pdftotext.exe and arrived at the following:
$confirmation = Read-Host "Press Y to proceed, any other key to cancel!" if ($confirmation -eq 'y') { $files = Get-ChildItem "*.pdf" foreach ($f in $files){ $newname = ( .\pdftotext.exe $f - | findstr "For:" | %{ $_.Split(' ')[-1];} | %{ $_.Split('[()]')[1];} ) $newname = $newname + ".pdf" "$f => $newname" Rename-Item $f $newname } pause }
The Windows installation did not allow[7] to execute the .ps1
file with a double-click, so we needed a small wrapper script (.bat
) to help here:
powershell -ExecutionPolicy ByPass -File pdf_rename.ps1
Playing sounds
This even works from a plain command line:[8]
powershell -c (New-Object Media.SoundPlayer 'c:\users\dummy\test.wav').PlaySync();
Battery status
Via wmic
:WMIC: WMI command-line utility</ref>
$ wmic path Win32_Battery get EstimatedChargeRemaining EstimatedChargeRemaining 68
The powercfg
[9] command creates a nice HTML report:
powercfg /batteryreport
CMD
while
loop
@echo off setlocal enableextensions enabledelayedexpansion set /a "x = 0" :while1 if %x% leq 5 ( echo %x% set /a "x = x + 1" goto :while1 ) endlocal
for
loop
for /l %a in (1, 1, 100) do echo %a
Or, when operating on files:
for /f %a in ('dir /b /d') do move %a dir\%a
Move all files in all subdirectories into one single directory:
mkdir single_dir cd subdir_structure for /r %d in (*) do move "%d" ..\single_dir
forfiles
There's also forfiles available for Windows Vista and later versions (or via the Windows Resource Kit[10]), that can do things like delete files older than N days[11]:
forfiles /p "c:\what\ever" /s /m *.* /d <number of days> /c "cmd /c del @path"
To expand on that, find recent files greater than 200 MB:[12][13]
$ forfiles /p c:\ /s /d +"11/01/2023" /c "cmd /c if @fsize gtr 209715200 echo @path @fsize @fdate @ftime" "C:\pagefile.sys" 1073741824 11/2/2023 5:03:32 PM "C:\Users\root\AppData\Local\VirtualStore\Windows\DataStore.edb" 604045312 11/2/2023 5:11:51 PM "C:\Windows\SoftwareDistribution\DataStore\DataStore.edb" 604045312 11/2/2023 5:19:22 PM "C:\Windows\winsxs\ManifestCache\702349c5b78f9a04_blobs.bin" 211158729 11/2/2023 5:44:16 PM
/dev/null
echo "hello" > NUL
date/time
$ echo %date%%time% 27.07.2011 4:44:21,50
tee
This really just redirects stdout
to a file and then[14] displays it:
dir > a.txt && type a.txt
wmic
Gather version information with wmic
[15]:
$ wmic datafile where name='c:\\Program Files\\7-Zip\\7z.exe' get version Version 9.20.0.0
- The double backslashes are important.
- Only single quotes will work, double quotes will produce an error.
Gather installed software packages:[16]
$ wmic softwarefeature get productname,version | find /i "zip" 7-Zip 9.34 9.34.00.0
Links
- Stackoverflow: while loop in batch
- Stackoverflow: Batch script loop
- Stackoverflow: /dev/null in Windows
- Stackoverflow: current date/time in Windows
- Stackoverflow: tee in Windows
- Windows Programming: Programming CMD
References
- ↑ The Windows PowerShell Profile
- ↑ Create Custom Windows PowerShell Profiles (.ps1)
- ↑ Perfect Prompt for Windows PowerShell
- ↑ How to sudo on powershell on Windows
- ↑ AWK equivalent in Windows Powershell
- ↑ Getting Personal With PowerShell: Linux to PowerShell
- ↑ Set-ExecutionPolicy
- ↑ How to play audio file on windows from command line?
- ↑ Powercfg command-line options
- ↑ Windows Server 2003 Resource Kit Tools
- ↑ Batch file to delete files older than N days
- ↑ Is there a Windows command-line utility to list largest files exceeding specific size in sub-directories?
- ↑ how to find large files in command line windows for version 5.1
- ↑ Multiple Commands on a Single Line May Not Run When You Use the && Command Separator
- ↑ Windows Management Instrumentation: WMI Command Line Tools
- ↑ WMI: Get the list of Installed Softwares