Bash中单行while循环的语法

857

我在使用分号和/或大括号的组合时遇到了麻烦。我想在命令行上将其作为一行代码完成:

while [ 1 ]
do
    foo
    sleep 2
done

5
将换行符替换为分号。对于for循环也是一样的。 - Tom
24
@Tom:那并不总是有效。在“do”之后,必须有第一个命令,而不是一个分号。 - Stefano Borini
15个回答

6

甚至不需要使用 dodone。对于无限循环,我发现使用带有大括号的 for 更易读。例如:

for ((;;)) { date ; sleep 1 ; }

这在bashzsh中有效,但在sh中无效。

2
如果我可以给出两个实际的例子(带有一些“情感”)。
这段代码会在文件夹“img”中写下所有以“.jpg”结尾的文件名:
for f in *; do if [ "${f#*.}" == 'jpg' ]; then echo $f; fi; done

这将删除它们:

for f in *; do if [ "${f#*.}" == 'jpg' ]; then rm -r $f; fi; done

只是想做出一点贡献。


1
@JKnight - 对于这些示例,你只需执行 ls -1 *.jpgrm *.jpg 即可。 - Kevin Fegan
2
两者都不是无限循环也不是while循环。 - Marian

2
你也可以尝试这个方法 警告:你不应该这样做,但既然问题要求无限循环...这就是你可以这样做的方式。
while [[ 0 -ne 1 ]]; do echo "it's looping";   sleep 2; done

你为什么要这样做? - gniourf_gniourf
3
因为Brian Deacon发布了这个问题,他想要一个无限循环。这只是有多种方法来解决问题。 - grepit
为什么不应该呢? - TheTechRobo the Nerd

1
你也可以将该循环放置在后台(例如,当你需要从远程机器断开时)。
nohup bash -c "while true; do aws s3 sync xml s3://bucket-name/xml --profile=s3-profile-name; sleep 3600; done &"

我一直试图避免这种情况,原因是你的编辑器可能无法将字符串上下文突出显示为程序语法。 - Sridhar Sarnobat

0
在(甚至更早版本)中,您还可以通过在循环条件中运行所有内容但在循环体中使用:来反转:的角色。
while ( gdate +"%c ( %s.%-N )" && sleep 0.71  ) do :; done  # discards side-effects
      
while { gdate +"%c ( %s.%-N )" && sleep 0.71; } do :; done  # no sub-shell needed

+ gdate '+%c ( %s.%-N )'
Sun Apr 30 12:38:25 2023 ( 1682872705.498728 )
+ sleep 0.71
+ :

+ gdate '+%c ( %s.%-N )'
Sun Apr 30 12:38:26 2023 ( 1682872706.218152 )
+ sleep 0.71

... 

与此同时,zsh 更加宽容,即使没有 :,也愿意循环执行。

while; do gdate +'%c ( %s.%-N )' && sleep 0.31 ; done

Sun Apr 30 12:46:09 2023 ( 1682873169.469092 )
Sun Apr 30 12:46:09 2023 ( 1682873169.789560 )
Sun Apr 30 12:46:10 2023 ( 1682873170.105635 )
Sun Apr 30 12:46:10 2023 ( 1682873170.424766 )

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接