93

I'm looking for a Windows program/script/command line function that works like Linux's watch program.

watch periodically calls another program/whatever and shows the result, which is great for refreshing an output file or similar every second:

watch cat my-output.txt

or, more powerfully:

watch grep "fail" my-output.txt

I've looked for it in cygwin's library, but it doesn't seem to be present.

1
  • Hey anon, while (1) { cls;kubectl get nodes; sleep 5} Thank me later.
    – RSW
    Mar 9, 2023 at 9:39

16 Answers 16

22

watch is available in Cygwin, in the procps-ng⁰ package as listed here (this info can be found via the package search on the website, here). I don't think this package is installed by the default cygwin setup, but it is one I usually select on new installs in order to have the watch command available.

The location of tools in packages typically match package names in Linux distributions (the package containing watch is procps on Debian and Ubuntu too) so if the Cygwin package search function fails you, info for/from Linux distributions may offer clues. In this example the exact naming is no longer the case, though searching for procps would find procps-ng.

--

[0] procps is now deprecated (as noted here and here), the original package stopped being maintained and a couple of distros forked it to apply pending patches. In some places it is still called procps but in others like cygwin the new name was used

2
  • How is this and answer? Jul 29, 2023 at 14:48
  • @ScienceDiscoverer – the question asked for something like watch under Windows. What is it about running watch in Windows (via the cygwin port) that you don't think is sufficiently like watch for Windows? Jul 31, 2023 at 9:41
63

Write your own. Let's say file watch.bat contains :

@ECHO OFF
:loop
  cls
  %*
  timeout /t 5 > NUL
goto loop

and call it via, for example:

watch echo test

will echo test every 5 seconds.

6
  • 1
    @Keilaron: Note that your edit was bad and I had to fix it.  Please be more careful. Dec 13, 2017 at 19:35
  • Simple but great. Avoids installing cygwin just for that single command. Vielen Dank!
    – Stef
    Feb 12, 2019 at 5:23
  • Great! This should be the accepted answer! ;)
    – zsolt
    Feb 21, 2021 at 13:25
  • Is there a way to make it accept the timeout parameter as an argument?
    – Shayan
    Feb 4, 2023 at 14:08
  • 1
    @Shayan yes, easily. Just use %1 for the first argument like this: timeout /t %1 > nul Jul 29, 2023 at 14:49
52

Powershell has the while command. You can use it like in Linux:

while (1) {your_command; sleep 5}

Linux version:

while true; do your_command; sleep5; done

Others:

while ($true) {netstat -an | findstr 23560; sleep 5; date}
3
  • 6
    You can just use while (1), because 1 is truthy. May 14, 2016 at 12:05
  • 6
    I also found that you can use "clear" as the last statement, so it behaves more like watch.
    – itmuckel
    Nov 11, 2016 at 7:51
  • To better mimic watch you can also use date -format s as the first command to show the time. May 17, 2023 at 20:17
20

A generic Windows command oneliner to accomplish this:

for /l %g in () do @( echo test & timeout /t 2 )

Replace "echo test" with the command you wish to run repeatedly.

1
  • 1
    nice one, simple one liner that does the trick
    – user230910
    Sep 25, 2017 at 12:58
9

It's a PowerShell one liner:

while ($true) { <your command here> | Out-Host; Sleep 5; Clear }
2
  • I'd put Clear first.
    – sastanin
    Oct 5, 2018 at 15:53
  • it depends on how long your command takes to run and then output to display.... you can change the order, but this is the general idea
    – ErikW
    Apr 30, 2019 at 15:13
8

I wrote this little PowerShell module to do what you were looking for. Just put it in

C:\Users\[username]\Documents\WindowsPowerShell\Modules\Watch

and run import-module watch in PowerShell.


# ---- BEGIN SCRIPT
# Author:       John Rizzo
# Created:      06/12/2014
# Last Updated: 06/12/2014
# Website:      http://www.johnrizzo.net

function Watch {
    [CmdletBinding(SupportsShouldProcess=$True,ConfirmImpact='High')]
    param (
        [Parameter(Mandatory=$False,
                   ValueFromPipeline=$True,
                   ValueFromPipelineByPropertyName=$True)]
        [int]$interval = 10,

        [Parameter(Mandatory=$True,
                   ValueFromPipeline=$True,
                   ValueFromPipelineByPropertyName=$True)]
        [string]$command
    )
    process {
        $cmd = [scriptblock]::Create($command);
        While($True) {
            cls;
            Write-Host "Command: " $command;
            $cmd.Invoke();
            sleep $interval;
        }
    }
}

Export-ModuleMember -function Watch

# --- END SCRIPT
2
  • 1
    Looks pretty good but I would encourage the function to be in the Verb-Noun format (e.g. Watch-Command) with an alias of Watch (Set-Alias -Name Watch -item Watch-Command). Mar 8, 2019 at 18:24
  • Thanks! See my answer for some improvements I added
    – Wesley
    Oct 30, 2020 at 8:08
8

This is how I would do it in PowerShell:

while(1){ netstat -an|grep 1920;start-sleep -seconds 2;clear }

The condition while(1) is equivalent to while true, looping indefinitely.

3

You can also make up a delay using the PING command, for example:

@echo off
:loop
  cls
  dir c:\temp
  REM 5000mS (5 sec) delay...
  ping 1.1.1.1 -n 1 -w 5000 >NUL
goto loop
2

I had the same issue when needing to check the file size of a file actively being worked on by another process. I ended up cloning the functionality of watch on Windows. The compiled exe as well as the source is available at the site.

watch for Windows

2

I created a watch command for windows called llwatch.

The code is both on my website landenlabs.com

and also on GitHub

You may need to use x64 to watch x64 programs and x32 for the others. Not sure how picky windows is.

1
  • Not sure why this was downvoted... Welcome to Super User!
    – jpaugh
    Feb 2, 2016 at 14:16
1

what @harrymc said except with sleep watch.bat

@ECHO OFF
:loop
  %*
  sleep 5
goto loop

./watch.bat npm run test

npm run test every 5 sec

1

You can use this command in windows cmd (not working in powershell):

for /l %g in () do @( <your-command> & timeout /t 1 > nul )

The /t value is in seconds

This prevent the timeout command to write "Waiting for n seconds ..." so it's kind of silent.

If you want to go faster than 1 second you can do the following:

for /l %g in () do @( <your-command> & ping 127.0.0.1 -n 1 -w 500 > nul )
0

PowerShell-Watch

Code Repository

0

Some improvements on the excellent PS module written by johnrizzo1 (see here)

  • Renamed function to be in line with Powershell naming convention (as suggested by duct_tape_coder)
  • Moved interval to second argument, so it's optional; reduced default to 2 seconds
  • Fetch output of Invoke first, only then refresh the screen. This avoids the screen going blank while the command executes
function Watch-Command {
    [CmdletBinding(SupportsShouldProcess=$True,ConfirmImpact='High')]
    param (
        [Parameter(Mandatory=$True,
                   ValueFromPipeline=$True,
                   ValueFromPipelineByPropertyName=$True)]
        [string]$command,

        [Parameter(Mandatory=$False,
                   ValueFromPipeline=$True,
                   ValueFromPipelineByPropertyName=$True)]
        [int]$interval = 2
    )
    process {
        $cmd = [scriptblock]::Create($command);
        While($True) {
            $output = $cmd.Invoke();
            cls;
            Write-Host "Command: " $command;
            Write-Host ($output | Out-String);
            sleep $interval;
        }
    }
}
0
while(1) { clear; Command ;sleep 3; }
1
  • 1
    While this code may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value. Dec 18, 2020 at 9:33
-2

I was in a hurry.... I used one suggestion and changed it a little to work for me:

for /l %g in () do @( echo test & timeout /t 2 )

I changed it to:

for /l %g in () do @( test.bat & timeout /t 2 )

And I created the test.bat file with the command line. In my case, it was:

net group <NAME> /domain

I found that the echo command just printed out to the screen but did not execute the command

1
  • "the echo command just printed out to the screen" - that's exactly what the echo command does Jan 9, 2023 at 18:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .