如何在Bash中重复循环n次


9

我有以下情况:

if [file exists]; then
   exit   
elif
   recheck if file exist (max 10 times)
   if found exit else recheck again as per counter  
fi 

这是Shell中非常基本的功能。你甚至研究了吗?
Peschke '18

是。但是没有从我的代码中获得预期的输出。也想写得尽可能
短一些

1
@Peschke,好吧,他们至少需要三个基本功能(循环,条件,测试文件,脱离循环)。至少问题是很清楚的。尽管它可以包含洛基尝试过的内容的草图,但是无论如何有人会在答案中完全重写它。;)
ilkkachu

Answers:


9

有很多方法可以执行此循环。

随着ksh93语法(也支持zshbash):

for (( i=0; i<10; ++i)); do
    [ -e filename ] && break
    sleep 10
done

对于任何类似POSIX的外壳:

n=0
while [ "$n" -lt 10 ] && [ ! -e filename ]; do
    n=$(( n + 1 ))
    sleep 10
done

在再次测试文件是否存在之前,两个循环在每次迭代中均休眠10秒。

循环完成后,您将不得不最后一次测试文件是否存在,以弄清循环是由于运行10次还是由于文件出现而退出。

如果愿意,并且可以访问inotify-tools,可以将sleep 10呼叫替换为

inotifywait -q -t 10 -e create ./ >/dev/null

这将等待文件创建事件在当前目录中发生,但会在10秒后超时。这样,一旦给定的文件名出现(如果出现),循环就会退出。

完整的代码(带有inotifywaitsleep 10如果不需要的话替换为))可能看起来像

for (( i=0; i<10; ++i)); do
    [ -e filename ] && break
    inotifywait -q -t 10 -e create ./ >/dev/null
done

if [ -e filename ]; then
    echo 'file appeared!'
else
    echo 'file did not turn up in time'
fi

使用inotify,您几乎可以替换整个循环。只需测试文件是否存在,如果没有,则等待100秒。几乎,因为文件可以创建只是测试和inotify的之间,和你睡了整整100秒钟后超时...
ilkkachu

1
@ilkkachu是的,这是个好主意,但在这里我只是inotifywait用作的替代品sleep
库萨兰达

8

如果计数不是变量,则可以使用大括号扩展:

for i in {1..10}   # you can also use {0..9}
do
  whatever
done

如果count是变量,则可以使用以下seq命令:

count=10
for i in $(seq $count)
do
  whatever
done

我只想在找不到文件的情况下循环播放(最多10次)。如果发现让我们说第3次,则成功退出
Rocky86 '18

@ Rocky86:这与xenoid提出的解决方案并不矛盾。没人强迫你数到最后....
user1934428 '18

我喜欢这个$(seq $count)
工作者

0
n=0
until [ "$((n+=1))" -gt 10 ]
do    <exists? command exit
done
echo oh noes!

虽然test -e file && exit更灵活


为什么问号?请注意,重定向目标中的全局行为在外壳之间有所不同。
斯特凡Chazelas

2
请注意,它有打开文件,这对于FIFO中,例如可以是相当糟糕的(用符号链接到/ dev /看门狗在Linux例如更糟)的副作用
斯特凡Chazelas

即使在Bash中,它会查找类似文件exists1,如果/找不到匹配的文件,它仍会打印出许多错误。(如果有多个匹配项,它也会出错。)我测试过的任何其他外壳在任何情况下都似乎给出了错误……
ilkkachu

@ikkachu-是的 这就是重点。如果发生错误,脚本将报告。如果应该抑制stderr,请抑制它done 2<>/dev/null。DOE中bash确实是脚本?我认为这只是在互动-i环境下才有效。仍然exists?是和一样的填充名称file。但是,是的,我讨厌引述重定向-如果螺丝这么 多了。
mikeserv '18

@Stéphane-没理由,真的。但是,是的,fifos,无法读取...这就是为什么我注意到了test -e
mikeserv
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.