I am having trouble coming up with the right combination of semicolons and/or braces. I'd like to do this, but as a one-liner from the command line:
while [ 1 ]
do
foo
sleep 2
done
while true; do foo; sleep 2; done
By the way, if you type it as a multiline (as you are showing) at the command prompt and then call the history with arrow up, you will get it on a single line, correctly punctuated.
$ while true
> do
> echo "hello"
> sleep 2
> done
hello
hello
hello
^C
$ <arrow up> while true; do echo "hello"; sleep 2; done
It's also possible to use sleep command in while's condition. Making one-liner looking more clean imho.
while sleep 2; do echo thinking; done
while echo thinking ; do sleep 2 ; done
Of course if the [while] command fails, the loop exits, so you would have to while echo thinking || true ; do sleep 2 ; done
but then you are back to while true ; ...
Colon is always "true":
while :; do foo; sleep 2; done
: [arguments]
No effect; the command does nothing beyond expanding arguments and performing any specified redirections. A zero exit code is returned.
You can use semicolons to separate statements:
$ while [ 1 ]; do foo; sleep 2; done
You can also make use of until
command:
until ((0)); do foo; sleep 2; done
Note that in contrast to while
, until
would execute the commands inside the loop as long as the test condition has an exit status which is not zero.
Using a while
loop:
while read i; do foo; sleep 2; done < /dev/urandom
Using a for
loop:
for ((;;)); do foo; sleep 2; done
Another way using until
:
until [ ]; do foo; sleep 2; done
until ((0)); do foo; sleep 2; done
does not seem to work. It continuous infinite.
Using while
:
while true; do echo 'while'; sleep 2s; done
Using for
Loop:
for ((;;)); do echo 'forloop'; sleep 2; done
Using Recursion
, (a little bit different than above, keyboard interrupt won't stop it)
list(){ echo 'recursion'; sleep 2; list; } && list;
sleep
, like sleep 1h
. In my zsh, it ignores the unit h
and runs my command every 1 second. Do a quick man sleep
to see what your environment's sleep
command supports first. May save you a headache.
A very simple infinite loop.. :)
while true ; do continue ; done
Fr your question it would be:
while true; do foo ; sleep 2 ; done
For simple process watching use watch
instead
I like to use the semicolons only for the WHILE statement, and the && operator to make the loop do more than one thing...
So I always do it like this
while true ; do echo Launching Spaceship into orbit && sleep 5s && /usr/bin/launch-mechanism && echo Launching in T-5 && sleep 1s && echo T-4 && sleep 1s && echo T-3 && sleep 1s && echo T-2 && sleep 1s && echo T-1 && sleep 1s && echo liftoff ; done
&&
in the loop is the same as any other time really isn't it. Do you need the second thing to happen only if the first happens, then use &&
else ;
suffices. Really, you want to keep the contents of that loop short and simple, ideally just one command, so a function or a script.
sleep
, like sleep 1h
. In my zsh, it ignores the unit h
and runs my command every 1 second. Do a quick man sleep
to see what your environment's sleep
command supports first. May save you a headache.
If you want the while loop to stop after some condition, and your foo
command returns non-zero when this condition is met then you can get the loop to break like this:
while foo; do echo 'sleeping...'; sleep 5; done;
For example, if the foo
command is deleting things in batches, and it returns 1 when there is nothing left to delete.
This works well if you have a custom script that needs to run a command many times until some condition. You write the script to exit with 1
when the condition is met and exit with 0
when it should be run again.
For example, say you have a python script batch_update.py
which updates 100 rows in a database and returns 0
if there are more to update and 1
if there are no more. The the following command will allow you to update rows 100 at a time with sleeping for 5 seconds between updates:
while batch_update.py; do echo 'sleeping...'; sleep 5; done;
foo
command exit with code 1
when you want the while loop to break. I've updated my answer with an example.
You don't even need to use do
and done
. For infinite loops I find it more readable to use for
with curly brackets. For example:
for ((;;)) { date ; sleep 1 ; }
This works in bash
and zsh
. Doesn't work in sh
.
If I can give two practical examples (with a bit of "emotion").
This writes the name of all files ended with ".jpg" in the folder "img":
for f in *; do if [ "${f#*.}" == 'jpg' ]; then echo $f; fi; done
This deletes them:
for f in *; do if [ "${f#*.}" == 'jpg' ]; then rm -r $f; fi; done
Just trying to contribute.
ls -1 *.jpg
and rm *.jpg
You can try this too WARNING: this you should not do but since the question is asking for infinite loop with no end...this is how you could do it.
while [[ 0 -ne 1 ]]; do echo "it's looping"; sleep 2; done
You can also put that loop in the background (e.g. when you need to disconnect from a remote machine)
nohup bash -c "while true; do aws s3 sync xml s3://bucket-name/xml --profile=s3-profile-name; sleep 3600; done &"
Success story sharing
cmdhist
option if you are using bash?while true; do sh /Users/myuser/bin/vpn ; done