• Stars
    star
    674
  • Rank 66,980 (Top 2 %)
  • Language
    Rust
  • License
    MIT License
  • Created over 6 years ago
  • Updated about 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

UNIX's missing `loop` command

Logo, with help from Linn Kristiansen

loop Build Status crates.io

"UNIX's missing loop command!"

loop lets you write powerful, intuitive looping one-liners in your favorite shell! Finally, loops in Bash that make sense!

Why?

Loops in bash are surprisingly complicated and fickle! I wanted a simple and intuitive way to write controllable loops that:

  • Run on controllable timers!

    • $ loop --every 10s -- ls
  • Have custom counters!

    • $ loop --count-by 5 -- 'touch $COUNT.txt'
  • Loop until output matches a condition!

    • $ loop --until-contains 200 -- ./get_response_code.sh --site mysite.biz
  • Loop until a certain time!

    • $ loop --for-duration 8h -- ./poke_server
  • Loop until a program succeeds (or fails!)

    • $ loop --until-success -- ./poke_server
  • Iterate over the standard input!

    • $ cat files_to_create.txt | loop -- 'touch $ITEM'
  • Get a summary of the runs!

    • $ loop --for-duration 10min --summary -- ls
  • Run until output changes or stays the same between invocations!

    • $ loop --until-changes -- date +%s
    • $ loop --until-same -- date +%s
  • ..and much more!

And so loop was born!

Installation

Linux

loop is available on Snapcraft for all distributions as loop-rs.

$ snap install loop-rs --beta

Issues related to this package are tracked here.

There is also an AUR for Arch Linux users, but I don't maintain it, so use it at your own risk:

$ yaourt -S loop

OSX

If you're a Homebrew user:

$ brew tap miserlou/loop https://github.com/Miserlou/Loop.git
$ brew install loop --HEAD

Rust Users

$ cargo install loop-rs

Building

$ cargo build
./debug/loop
$ cargo run 'echo $COUNT'
1
2
[ .. ]

Usage

With no arguments, loop will simply repeatedly execute a command string as fast as it can until ^C (control + C) is sent.

$ loop 'echo hello'
hello
hello
hello
hello
[ .. ]

You can also use double dashes ( -- ) to seperate arguments:

$ loop -- echo hello
hello
hello
hello
hello
[ .. ]

Counters

loop places a counter value into the $COUNT environment variable.

$ loop -- 'echo $COUNT'
0
1
2
[ .. ]

The amount this counter increments can be changed with --count-by:

$ loop --count-by 2 -- 'echo $COUNT'
0
2
4
6
[ .. ]

The counter can be offset with --offset:

$ loop --count-by 2 --offset 10 -- 'echo $COUNT'
10
12
14
[ .. ]

And iterators can be floats!

$ loop --count-by 1.1 -- 'echo $COUNT'
0
1.1
2.2
[ .. ]

There's also an $ACTUALCOUNT:

$ loop --count-by 2 -- 'echo $COUNT $ACTUALCOUNT'
0 0
2 1
4 2
[ .. ]

You can get a summary of successes and failures (based on exit codes) with --summary:

$ loop --num 3 --summary -- 'echo $COUNT'
0
1
2
Total runs:  3
Successes:   3
Failures:    0

or

$ loop --num 3 --summary -- 'ls -foobarbatz'
[ .. ]
Total runs:  3
Successes:   0
Failures:    3 (1, 1, 1)

If you only want the output of the last result, you can use --only-last:

$ loop --count-by 2 --num 50 --offset 2 --only-last -- 'echo $COUNT' # Counting is 0-indexed
100

Timed Loops

Loops can be set to timers which accept humanized times from the microsecond to the year with --every:

$ loop --every 5s -- date
Thu May 17 10:51:03 EDT 2018
Thu May 17 10:51:08 EDT 2018
Thu May 17 10:51:13 EDT 2018

Looping can be limited to a set duration with --for-duration:

$ loop --for-duration 8s --every 2s -- date
Fri May 25 16:46:42 EDT 2018
Fri May 25 16:46:44 EDT 2018
Fri May 25 16:46:46 EDT 2018
Fri May 25 16:46:48 EDT 2018
$

Or until a certain date/time with --until-time:

$ loop --until-time '2018-05-25 20:50:00' --every 5s -- 'date -u'
Fri May 25 20:49:49 UTC 2018
Fri May 25 20:49:54 UTC 2018
Fri May 25 20:49:59 UTC 2018
$

Until Conditions

loop can iterate until output contains a string with --until-contains:

$ loop --until-contains "666" -- 'echo $RANDOM'
11235
35925
666
$

loop can iterate until the output changes with --until-changes:

$ loop --only-last --every 1s --until-changes -- 'date +%s'
1548884135
$

loop can iterate until the output stays the same with --until-same. This would be useful, for instance, for monitoring with du until a download or copy finishes:

$ loop --every 1s --until-same -- 'du -bs .'
236861997       .
$

Or until a program succeeds with --until-success:

$ loop --until-success -- 'if (( RANDOM % 2 )); then (echo "TRUE"; true); else (echo "FALSE"; false); fi'
FALSE
FALSE
TRUE
$

Or until it fails with --until-error (which also accepts an optional error code):

$ loop --until-error -- 'if (( RANDOM % 2 )); then (echo "TRUE"; true); else (echo "FALSE"; false); fi'
TRUE
TRUE
FALSE
$

Or until it matches a regular expression with --until-match:

$ loop --until-match "(\d{4})" -- `date`
Thu May 17 10:51:03 EDT 2018
$

Iterating Over Lists and Standard Inputs

Loops can iterate over all sorts of lists with --for:

$ loop --for red,green,blue -- 'echo $ITEM'
red
green
blue
$

And can read from the standard input via pipes:

$ cat /tmp/my-list-of-files-to-create.txt | loop -- 'touch $ITEM'
$ ls
hello.jpg
goodbye.jpg

This can be combined with various flags, such as --until-changes:

$ printf "%s\n" 1 1 3 | loop --until-changes -- echo '$ITEM'
1
1
3

$ seq 10 | loop --until-changes -- echo '$ITEM'
1
2

You can also easily pipe lists to loop:

$ ls -1 | loop -- 'cp $ITEM $ITEM.bak'; ls
hello.jpg
hello.jpg.bak

..or via the keyboard with -i:

$ loop -- 'echo $ITEM | tr a-z A-Z' -i
hello
world^D
HELLO
WORLD

--for can accept all sorts of lists:

$ loop --for "`ls`" -- 'echo $ITEM'
Cargo.lock
Cargo.toml
README.md
src
target
$

Useful Examples

Here are some handy things you can do with loop!

Testing inputs to a program

If you have a lot of files and a program, but don't know which file is the one the program takes, you can loop over them until you find it:

$ ls  -1 | loop --until-success -- './my_program $ITEM';

Or, if you have a list of files but need to find the one which causes your program to fail:

$ ls  -1 | loop --until-fail -- './my_program $ITEM';

Waiting for a website to appear online

If you've just kicked off a website deployment pipeline, you might want to run a process when the site starts returning 200 response codes. With --every and --until-contains, you can do this without flooding the site with requests:

$ ./deploy.sh; loop  --every 5s --until-contains 200 -- 'curl -sw "%{http_code}" http://coolwebsite.biz'; ./announce_to_slack.sh

Or until a host is online:

$ loop --until-success -- ping -c 1 mysite.com; ./do_next_thing

Waiting for a file to be created

If you have a long-running process that creates a new file, you might want to kick off another program when that process outputs a new file, like so:

$ ./create_big_file -o my_big_file.bin; loop --until-contains 'my_big_file.bin' -- 'ls'; ./upload_big_file my_big_file.bin

Create a backup for all files in a directory

If you've got a whole list of files that you want to create backup copies of, you can do it like so:

$ ls
hello.jpg
$ ls -1 | loop -- 'cp $ITEM $ITEM.bak'
$ ls
hello.jpg
hello.jpg.bak

Keep trying a failing script until it passes, up to 5 times

This is an example from StackExchange.

I want to write logic in shell script which will retry it to run again after 15 sec upto 5 times based on "status code=FAIL" if it fails due to some issue.

There are so many questions like this on StackExchange, which all end up with long threads of complicated answers.

With loop, it's a simple one liner:

loop --every 15s --until-success --num 5 -- './do_thing.sh'

Which will do the thing every 15 seconds until it succeeds, for a maximum of five times.

Keep trying a failing script until timeout

If dealing with a command or script that occasionally fails in a CI environment, you may want to try for a given amount of time before giving up and failing the build.

With loop you can do that with:

loop --every 5s --until-success --for-duration 180s --duration-error -- './do_thing.sh'

Which will do the thing every 5 seconds until it succeeds or until the duration is met. If the duration is met, it will give the same non-zero return as the timeout command 124.

Comparison with GNU Parallel

This thread on Reddit with GNU Parallel author Ole Tange has some interesting side-by-side comparisons between loop and parallel.

More examples

Got any more useful examples? Send a pull request!

Contributing

This project is still young, so there is still plenty to be done. Contributions are more than welcome!

Please file tickets for discussion before submitting patches. Pull requests should target master and should leave Loop in a "shippable" state if merged.

If you are adding a non-trivial amount of new code, please include a functioning test in your PR. The test suite will be run by Travis CI once you open a pull request. Please include the GitHub issue or pull request URL that has discussion related to your changes as a comment in the code (example). This greatly helps for project maintainability, as it allows us to trace back use cases and explain decision making. Similarly, please make sure that you meet all of the requirements listed in the pull request template.

Please feel free to work on any open ticket, especially any ticket marked with the "help-wanted" label!

License

(c) Rich Jones, 2018-2019+. MIT License.

More Repositories

1

Zappa

Serverless Python
Python
11,887
star
2

Glance-Bookmarklet

A Speed Reading Bookmarklet
JavaScript
1,557
star
3

SoundScrape

SoundCloud (and Bandcamp and Mixcloud) downloader in Python.
Python
1,393
star
4

lambda-packages

Various popular python libraries, pre-compiled to be compatible with AWS Lambda
Shell
732
star
5

dnd-tldr

Dungeons and Dragons - Too Long; Didn't Read
625
star
6

DirtyShare

Peer to Peer Filesharing in Pure Javascript With Node.js and Socket.io
JavaScript
487
star
7

django-zappa

THIS PROJECT IS DEPRECATED, GO HERE INSTEAD:
Python
470
star
8

NoDB

NoDB isn't a database.. but it sort of looks like one.
Python
380
star
9

chords2midi

Create MIDI files from numerical chord progressions!
Python
352
star
10

Android-SDK-Samples

GitHub mirror of the Android SDK Samples. API version 17.
Java
300
star
11

omnihash

Hash files, strings, input streams and network resources in various common algorithms simultaneously
Python
251
star
12

Glance

Good reads, extremely fucking fast.
JavaScript
241
star
13

Minicraft

Minicraft and Minicraft for Android
220
star
14

django-easy-timezones

Easy timezones for Django based on GeoIP
Python
203
star
15

Mackenzie

AWS Lambda Infection Toolkit // Persistent Lambda Malware PoC
160
star
16

zappa-django-utils

A handy Django application to supercharge your Zappa deployments.
Python
144
star
17

live_json

LiveJSON - LiveView for JSON
JavaScript
131
star
18

NodeDeploy

Example scripts for deploying a Node.js application behind a Node proxy alongside Apache/Nginx, as a demon which restarts automatically upon crashing.
JavaScript
130
star
19

Helix

Engineering Consciousness
JavaScript
127
star
20

RJModules

Various modules for VCV Rack
C++
99
star
21

flask-zappa

Serverless Flask on AWS Lambda + API Gateway
Python
86
star
22

WhitespaceBot

Making GitHub Better.. With Robots
Python
79
star
23

UltimateTemplate

Ultimate Ableton Live Starter Template(s)
73
star
24

ADGMaker

Create Ableton Live Instruments from Philharmonia Samples
Smarty
73
star
25

django-knockout-modeler

Super simple knockout.js ModelView templates for you Django models
Python
50
star
26

zappa-bittorrent-tracker

An experimental server-less BitTorrent tracker. Powered by Zappa, Flask and (DynamoDB or S3).
Python
45
star
27

Zappa-CMS

A tiny serverless CMS for busy hackers.
HTML
42
star
28

FriendlyID

FriendlyID is an Elixir package that creates unique(-ish) friendly, human-readable identifiers for your objects.
Elixir
42
star
29

Hash-Identifier

GitHub Mirror of Hash-Identifier
Python
35
star
30

XSS-Harvest

XSS Weaponization
Perl
34
star
31

LightWrite

Online WriteRoom Clone
JavaScript
33
star
32

Fashion

Pythonic OpenFaaS. aka `python-openfaas`.
Python
33
star
33

OnionCloud

OnionCloud - An Anonymous Heroku-like PaaS
33
star
34

HitStarter

Anonymous Crowdfunding. BitCoin. Tor. You figure it out.
Python
32
star
35

zappa-slack-inviter

A server-less Slack inviter
HTML
32
star
36

Emo

Command line emoji search. 🙏 🔥
Python
29
star
37

JonesComplexity

Per-line complexity for Flake8
Python
29
star
38

VitalPresets

My Vital Presets for Vital Synth. Bass music, trap, drum and bass, IDM, wubs, wobbles, swooshes, fizzles, stomps and woops.
27
star
39

easy-expressions

Easy Regular Expressions for Python
Python
24
star
40

OpenWatch---Android

OpenWatch Client for Android
Java
20
star
41

Seek

Search the internet from your terminal. Speed read your results. Terminal nirvana.
Python
20
star
42

HerokuFreeProxy

A very very very very simple web proxy that runs on the Heroku free tier. Written in 2 minutes.
Python
20
star
43

Vape

COMMAND LINE AESTHETIC GENERATOR
Python
18
star
44

zappa-blog

A blog about Zappa, powered by Zappa. Zappa zappa zappa. Zappa.
HTML
17
star
45

WebP2P.org

The static pages from WebP2P.org
JavaScript
16
star
46

Zalgo

Ç͍̝͍͍͍͙͍͕͍͍͍̈́ͣͩo̴̵̧̧͍͍͍͍͍͈͍͍͍͍͍͍̻͍͍͍͍͍͍͍͍͍͍͍͍͍͕͍͍͂̈̾̀͐̌ͤ̈ͪ̌ͦͪ̚͢͝͠͡ͅm̵̶̢͍͍͍͍͍͍̪͍͍͍͍͍͍̤͍̬͍͍̯͍̳͍͍͍͍͙͍͍͍͍ͮ̃̂ͨͯ͑͂ͭ̏͌́̕҉̢̨͍͍̱͍͍͍͍͍͎͍͍͍͍̣͍͍͍͍̤͍͍͍̫͍̜͍̿̊͒ͤ̏͌ͧ͝͝m͍͚͍͍͍͍͍͍̂ͧ̾ͬ͡a͍͏͍͍͋n͍̣͍͙͍͍̣͍͍̫͍̠͍̯͍͍͍͍ͦ̃̄̚̕d͍͍͍̣͍͍͍͍ͥͮ͊ͯ͠ ̡͍̖͍͍͍̝͍͍̺͍͍̺͍͍̞͍̟͍͍͍͍̳͍̭͍͍ͪ̾̉ͨ͂̂͘ͅ҈̸̧͍̝͍͍̰͍̬͍͍͍͍͍ͯ͟͡l̵͍̯͍͍͍͍̩͍͍̥͍͍͍̰͍̠͍͍͚͍͍͍͍̥͍͍̻͍͍͍͍͍͍̄ͯ́͒̒ͭ͂̏̽͞͠ i̴̷͍͍͍͍͍͍̰͍ͫ͑͝҈̴͍͍͍͍͍͍͍̜͍̘͍͍͍͍͍͆̿ͯ͋̆ͦ͋ͣ̆n͍͕͍̦͍͍ͅ͏̴͍̱͍͍͍͍̲͍͚͍͗̀e̢̧̡͍̖͍͍͍̟͍͕͍͍͍͍͍͍͍̱͍̟͍͍͍͍͍͍̻͍͍͍̠͍͍̖͍̅̓̊̅̂ͣ̀̽͆̅͘͜͠҉̴̷̶͍͍͍͙͍͍͍͍͍̰͍̫͍͍̜͍̱͍͍̘͍͍̙͍͍̫͍͇͍͍͍͍͍̲͍́̅͛̏̃̏ͥ̅ͨ́͝ ̴͍͍͍͍͍͍͍̯͍͍̜͍͍̙͍͍͍͍͍͓͍̹͍͍͍͍͍̲͍͍͍͉͍͍͍͍͍͍͍͍̦͍͚͍̣͍͍͍͍͍͉͍̦͍̰͍͍͍͍͍͍̃ͬͣ͋̾ͦͤ́ͦ̈̄͋̑ͪ̌ͫ̎̄͋̈ͨ̆ͩͥ̍͘̚̚̕͢͟͜͠z͍͍̠͍͍͍̥͍͍̠͍̀̉ͬ̕ą̴̸̴̡̛͍̜͍͍͍͍͎͍͍͍͍͍͍͍͍͍̗͍͍͍͍͍͍͍͍͍̠͍͈͍͍͍͍͍͍͍͍̮͍͍͍͍͍͍͍͍͍͍͍͍̮͍̪͍̍͐̇ͨͤ̈ͦ͋̽̋ͦͦ͋̍̒ͥ̉͂̿̑͊̇͂͢͟͟͢͜͡͠͝҉͍̬͍l̴̶̨̢̧̧͍̭͍͍͍͍͈͍͍͍͍͉͍̞͍͍͍͍͍͍͍͍͍̘͍͉͍̙͍͍̜͍͍͍͍͍̞͍͓͍͍̘͍͍͍͍͍͍͍͍̳͍͍͍͍͍̲͍͍̺͍͆̋ͧͣ͊̒̽͆ͬ̀͌ͥ́̈́̒ͭ̔̽̽̚͜͢͝ͅ҉͍͍̣͍͍̓͋ĝ͍͍͍̬͍͍͍̱͍ͭ̾͛҈̡͍̤͍͍͍͍͇͍͓͍͍͍̼͍͍̼͍͕͍͍̋̀̒ͪ͟͡o̶͍͍͍͍̖͍͍͍͍͍̙͍̰͍͍͍̘͍͍͍̤͍͇͍͖͍͍͋ͯͦ́̆̾̑ͮ̏̆͝.͍͍͋҉͍͍͍͍̱͍͍͍͆͐͒͐͢͏̡͍͍͈͍͍̩͍͍͍͍͍͍̥͍̯͍̺͍̣͍͍͍͍͍̠͍̗͍͍͍͍͍͍̘͍͍͍̅̔̋ͧ͂ͫ̒ͭ͊ͫ̓͊͌͆̔̕͝ͅ
Python
16
star
47

nogoogle

An easy way to remove Google from your life.
Python
15
star
48

Blaccupy

Black out your website to protest SOPA/PIPA
JavaScript
15
star
49

OpenWatch

OpenWatch.net code - Code for the client-side applications is available in my other repositories.
Python
15
star
50

django-aws-billing

Django AWS Usage/Billing Package.
Python
15
star
51

SynthRecipies

Random Serum Patches
14
star
52

django-easy-split

Easy split testing for Django.
Python
14
star
53

Exploitable

A Django application full of security holes for instructional purposes
JavaScript
14
star
54

Talks

A random, incomplete assortment of presentations
HTML
13
star
55

Poop

The internet is covered in 💩. Avoid it.
JavaScript
12
star
56

Youtube-Upload

GitHub Mirror of youtube-upload
12
star
57

CitizenMediaNotary

Citizen Media Notary creates notarized temporal records for citizen media.
JavaScript
12
star
58

django-easy-api

Give your website an API by changing a single line of code!
Python
11
star
59

ClickFraudBot

"If It's Digital, It Can Be Automated" ~ Tim Hwang
Python
11
star
60

django-welcome

Send welcome emails to new users and send notifications about new users to admins.
Python
11
star
61

b64img

Command line Base-64 image converter.
Python
10
star
62

Kaikai

Kaikai is like Bootstrap for WebVR projects. Let's have a Kaikai!
HTML
10
star
63

serverless-imagehost

Serverless thumbnailing service with Zappa and Flask
Python
10
star
64

Anomos

Anomos Github Mirror
Python
10
star
65

Trapify

KЄЄⱣ ΫØṲЯ ϾØMM∆ИƉ ⱢỊИЄ ₮ЯỊⱢⱢ, ₣∆M
Python
10
star
66

FreeScrub

A F/OSS metadata scrubber supporting PNG, PDF, TIFF, and JPEG files (with more to come!)
Python
9
star
67

stund

GitHub Mirror of stund
C++
8
star
68

LucidDreamBot

A Twitter bot to remind you to question reality. #onehourproject
Python
7
star
69

Cop-Recorder-2

Audio only version of the OpenWatch Android client. Sequel to Cop Recorder app
Java
7
star
70

ableton-backup

Backups of my Ableton Doodles. Not for you.
7
star
71

GrooveMac

A GrooveDown package for OSX
6
star
72

Tsunami

An Experimental BitTorrent Client. Ignore this for now.
JavaScript
6
star
73

progress.js

Towards an effort into making the internet into a progressive activist force. Simple, embeddable open source tools for progressive webmasters.
6
star
74

Karla

A Pen and Paper Game of Espionage
6
star
75

LaunchBoard

Guitar Mapping for the Novatation LaunchPad in Ableton Live
6
star
76

Voice-Dropbox

Asterisk Configuration to make a VoIP/PSTN Dropbox which integrates with OpenWatch.net
Python
6
star
77

kademlia.js

A Pure JavaScript Implementation of Kademlia. Towards a Decentralized WebDHT!
5
star
78

Spry

Spry is a slightly enhanced `pry` for Elixir
Elixir
5
star
79

Detour

GitHub mirror of Jann Horn's Detour
C
5
star
80

UniShare

UniShare - the engine behind NotesHub.org. A product of Students for Free Culture (freeculture.org)
JavaScript
5
star
81

pyglance

A Glance client and library for python for terminal speed reading.
Python
5
star
82

Spheres

Online Photosphere viewer and host.
HTML
5
star
83

gitlog

Show nicely formatted Git histories for multiple repositories for any given author.
Python
4
star
84

Android-Pay-What-You-Want

A library that lets you add Pay-What-You-Want donations to your project.
Java
4
star
85

simpleaws

A simpler way to create multi-user access on AWS. Built with Boto.
Python
4
star
86

LectureLeaks---Android

LectureLeaks Android Client
Java
4
star
87

Gunio-Android-Client

An Android app for Gun.io
Java
4
star
88

Autopan

BX$$ Autopan is a VST that automatically pans a signal back and forth between left and right channels.
4
star
89

RELIC

Regular Expressions Legislative Information Council
Python
4
star
90

django-devsafe

Safely work with a production database in an insecure environment
Python
4
star
91

Krasha

Crash Generation for Android. I made this in because I needed it. I don't know why anybody else would ever need this but what the hell, here it is.
Java
4
star
92

Stretches

Imagine one instant of a song, expanded to the size of the universe.
4
star
93

EOP945

Python Audio Squisher and Cut-up Maker
Python
3
star
94

DJMichael5000Botts

Auto-chopper and screwer in Python
Python
3
star
95

UppercaseMaker

Part of a Python Tutorial
Python
3
star
96

aDose

Brain Entrainment for Android. (Legacy Code)
Java
3
star
97

CrowdMap

A project to geospatially map the IP address space of international telecommunication companies
Java
3
star
98

OnionRTC

Experiments in using WebRTC over Tor. Nothing to see here yet.
Python
3
star
99

Chrominance

MIDI Visualizer
Python
3
star
100

Crusher

Inline PNG Crushing
Shell
3
star