9 个版本 (5 个破坏性更新)
使用旧的 Rust 2015
0.6.1 | 2019年2月8日 |
---|---|
0.6.0 | 2019年2月4日 |
0.5.0 | 2019年1月31日 |
0.4.0 | 2018年10月1日 |
0.1.0 | 2018年5月18日 |
#2663 在 命令行工具
每月 30 次下载
25KB
284 行
loop
"UNIX 缺失的 loop
命令!"
loop
允许你在最喜欢的 shell 中编写强大、直观的循环单行命令!最后,Bash 中有意义的循环!
为什么?
bash 中的循环非常复杂和反复无常!我希望有一个简单直观的方式来编写可控制的循环,
-
在可控制的 定时器 上运行!
$loop'ls' --every10s
-
有 自定义计数器!
$loop'touch $COUNT.txt' --count-by 5
-
循环 直到输出匹配 条件!
$loop --until-contains 200 --./get_response_code.sh --site mysite.biz
-
循环 直到一定时间!
$loop'./poke_server' --for-duration8h
-
循环 直到程序成功(或失败!)
$loop'./poke_server' --until-success
-
遍历 标准输入!
$cat files_to_create.txt | loop 'touch $ITEM'
-
获取运行 摘要!
$loop'ls' --for-duration10min --summary
-
运行直到输出在调用之间 更改或保持不变!
$loop --until-changesdate +%s
$loop --until-samedate +%s
-
等等 更多!
因此 loop
应运而生!
安装
Linux
loop
可在 Snapcraft 中以 loop-rs
的形式用于所有发行版。
$ snap install loop-rs --beta
与该软件包相关的问题在此 跟踪。
还有适用于Arch Linux用户的AUR,但我不维护它,所以请自行承担风险使用。
$ yaourt -S loop
OSX
如果您是Homebrew用户
$ brew tap miserlou/loop https://github.com/Miserlou/Loop.git
$ brew install loop --HEAD
Rust 用户
$ cargo install loop-rs
构建
$ cargo build
./debug/loop
$ cargo run 'echo $COUNT'
1
2
[ .. ]
用法
没有参数时,loop
会尽可能快速地重复执行命令字符串,直到按下^C
(Ctrl + C)。
$ loop 'echo hello'
hello
hello
hello
hello
[ .. ]
您也可以使用双横线(--
)来分隔参数。
$ loop -- echo hello
hello
hello
hello
hello
[ .. ]
计数器
loop
会将计数器的值放入$COUNT
环境变量中。
$ loop 'echo $COUNT'
0
1
2
[ .. ]
可以通过--count-by
更改计数器递增的量。
$ loop 'echo $COUNT' --count-by 2
0
2
4
6
[ .. ]
可以通过--offset
偏移计数器。
$ loop 'echo $COUNT' --count-by 2 --offset 10
10
12
14
[ .. ]
迭代器也可以是浮点数!
$ loop 'echo $COUNT' --count-by 1.1
0
1.1
2.2
[ .. ]
还有$ACTUALCOUNT
$ loop 'echo $COUNT $ACTUALCOUNT' --count-by 2
0 0
2 1
4 2
[ .. ]
使用--summary
可以获取成功和失败的总结(基于退出代码)。
$ loop 'echo $COUNT' --num 3 --summary
0
1
2
Total runs: 3
Successes: 3
Failures: 0
或者
$ loop 'ls -foobarbatz' --num 3 --summary
[ .. ]
Total runs: 3
Successes: 0
Failures: 3 (-1, -1, -1)
如果您只想获取最后一个结果,可以使用--only-last
。
$ loop 'echo $COUNT' --count-by 2 --num 50 --offset 2 --only-last # Counting is 0-indexed
100
计时循环
循环可以设置为定时器,该定时器接受从微秒到年份的人性化时间,使用--every
。
$ loop 'date' --every 5s
Thu May 17 10:51:03 EDT 2018
Thu May 17 10:51:08 EDT 2018
Thu May 17 10:51:13 EDT 2018
循环可以使用--for-duration
限制为特定时长。
$ loop 'date' --for-duration 8s --every 2s
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
$
或者直到某个日期/时间,使用--until-time
。
$ loop 'date -u' --until-time '2018-05-25 20:50:00' --every 5s
Fri May 25 20:49:49 UTC 2018
Fri May 25 20:49:54 UTC 2018
Fri May 25 20:49:59 UTC 2018
$
直到条件
loop
可以迭代,直到输出包含一个字符串,使用--until-contains
。
$ loop 'echo $RANDOM' --until-contains "666"
11235
35925
666
$
loop
可以迭代,直到输出改变,使用--until-changes
。
$ loop --only-last --every 1s --until-changes -- 'date +%s'
1548884135
$
loop
可以迭代,直到输出保持不变,使用--until-same
。例如,在用du
监控下载或复制操作完成时很有用。
$ loop --every 1s --until-same -- 'du -bs .'
236861997 .
$
或者直到程序成功,使用--until-success
。
$ loop 'if (( RANDOM % 2 )); then (echo "TRUE"; true); else (echo "FALSE"; false); fi' --until-success
FALSE
FALSE
TRUE
$
或者直到它失败,使用--until-error
(也可以接受一个可选的错误代码)。
$ loop 'if (( RANDOM % 2 )); then (echo "TRUE"; true); else (echo "FALSE"; false); fi' --until-error
TRUE
TRUE
FALSE
$
或者直到它匹配正则表达式,使用--until-match
。
$ loop 'date' --until-match "(\d{4})"
Thu May 17 10:51:03 EDT 2018
$
遍历列表和标准输入
循环可以使用--for
遍历所有类型的列表。
$ loop 'echo $ITEM' --for red,green,blue
red
green
blue
$
并且可以通过管道从标准输入读取。
$ cat /tmp/my-list-of-files-to-create.txt | loop 'touch $ITEM'
$ ls
hello.jpg
goodbye.jpg
这可以与各种标志结合使用,例如--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
您也可以轻松地将列表通过管道传递给loop
。
$ ls -1 | loop 'cp $ITEM $ITEM.bak'; ls
hello.jpg
hello.jpg.bak
或者通过键盘使用-i
。
$ loop 'echo $ITEM | tr a-z A-Z' -i
hello
world^D
HELLO
WORLD
--for
可以接受所有类型的列表。
$ loop 'echo $ITEM' --for "`ls`"
Cargo.lock
Cargo.toml
README.md
src
target
$
有用的示例
以下是您可以用loop
做的一些实用操作!
测试程序输入
如果您有很多文件和一个程序,但不知道哪个文件是程序所使用的,您可以循环遍历它们直到找到。
$ ls -1 | loop './my_program $ITEM' --until-success;
或者,如果您有一份文件列表,但需要找到导致程序失败的文件。
$ ls -1 | loop './my_program $ITEM' --until-fail;
等待网站上线
如果您刚刚启动了一个网站部署流程,您可能想在网站开始返回200响应代码时运行一个进程。使用--every
和--until-contains
,您可以这样做而不使网站充斥着请求。
$ ./deploy.sh; loop 'curl -sw "%{http_code}" http://coolwebsite.biz' --every 5s --until-contains 200; ./announce_to_slack.sh
或者直到主机在线。
$ loop "ping -c 1 mysite.com" --until-success; ./do_next_thing
等待文件创建
如果您有一个长时间运行的过程,它会创建新文件,那么当该过程输出新文件时,您可能想启动另一个程序,如下所示
$ ./create_big_file -o my_big_file.bin; loop 'ls' --until-contains 'my_big_file.bin'; ./upload_big_file my_big_file.bin
为目录中的所有文件创建备份
如果您有一系列文件需要创建备份,您可以这样做
$ ls
hello.jpg
$ ls -1 | loop 'cp $ITEM $ITEM.bak'
$ ls
hello.jpg
hello.jpg.bak
尝试失败的脚本,直到它通过,最多 5 次
这是一个来自StackExchange的示例。
我想在shell脚本中编写逻辑,使其在“status code=FAIL”的情况下重试运行,最多重试5次,每次重试间隔15秒。
StackExchange上有许多类似的问题,最终都以复杂的答案长线程结束。
使用loop
,这是一个简单的单行命令
loop './do_thing.sh' --every 15s --until-success --num 5
它将每15秒执行一次,直到成功,最多重试五次。
与 GNU Parallel 的比较
Reddit上的这个帖子,GNU Parallel作者Ole Tange在帖子中进行了loop
和parallel
的有趣比较。
更多示例
有更多有用的示例吗?请发送一个pull request!
贡献
这个项目还比较年轻,所以还有很多工作要做。欢迎贡献!
在提交补丁之前,请先提交讨论的票据。pull requests应该针对master
,如果合并,应该让Loop处于“可发货”状态。
如果您添加了大量的新代码,请在PR中包含一个功能测试。测试套件将在您打开pull request后由Travis CI运行。请将有关您的更改的GitHub问题或pull request URL作为代码中的注释(示例)。这将大大有助于项目的维护,因为它允许我们追踪用例并解释决策。同样,请确保您满足pull request模板中列出的所有要求。
请随意处理任何开放的票据,特别是任何标记有“help-wanted”标签的票据!
许可证
(c) Rich Jones, 2018-2019+. MIT License.
依赖项
~7–17MB
~231K SLoC