【问题标题】:while loop stops before false [duplicate]while循环在false之前停止[重复]
【发布时间】:2019-01-17 08:47:38
【问题描述】:

试图压缩所有日志,但目录中的日志除外。我知道还有其他方法可以完成我想做的事情,但我主要是好奇为什么会发生以下情况。

我有以下脚本:

#!/usr/bin/env bash

TOTAL=$(ls -lah ./*.log | wc -l)
let "TOTAL--"

COUNT=0
while [[ $COUNT < $TOTAL ]]; do
  gzip $(ls -1 | grep -v '.gz' | grep '.log' | head -n 1)
  let "COUNT++"
  echo "$TOTAL - $COUNT = $(($TOTAL-$COUNT))"
  sleep 2
done

要为此设置环境,您可以执行以下操作:

cd
mkdir tmp0
cd tmp0
touch test_{1..20}.log

然后将此脚本放在同一个目录中(是的,是的,您也可以设置一个 var 来引用该目录)。无论如何,当这样设置并运行时,它会在$COUNT 仍然小于$TOTAL 时停止:

[ec2-user@ip-172-31-0-70 ~]$ cd
[ec2-user@ip-172-31-0-70 ~]$ mkdir tmp0
[ec2-user@ip-172-31-0-70 ~]$ cd tmp0/
[ec2-user@ip-172-31-0-70 tmp0]$ touch test_{1..20}.log
[ec2-user@ip-172-31-0-70 tmp0]$ mv ../myscript.sh .
[ec2-user@ip-172-31-0-70 tmp0]$ ll
total 4
-rwxrwxr-x 1 ec2-user ec2-user 245 Aug  9 11:45 myscript.sh
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_10.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_11.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_12.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_13.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_14.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_15.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_16.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_17.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_18.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_19.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_1.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_20.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_2.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_3.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_4.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_5.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_6.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_7.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_8.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_9.log
[ec2-user@ip-172-31-0-70 tmp0]$ ./myscript.sh 
19 - 1 = 18
19 - 2 = 17
[ec2-user@ip-172-31-0-70 tmp0]$ ll
total 12
-rwxrwxr-x 1 ec2-user ec2-user 245 Aug  9 11:45 myscript.sh
-rw-rw-r-- 1 ec2-user ec2-user  32 Aug  9 12:24 test_10.log.gz
-rw-rw-r-- 1 ec2-user ec2-user  32 Aug  9 12:24 test_11.log.gz
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_12.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_13.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_14.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_15.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_16.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_17.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_18.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_19.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_1.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_20.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_2.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_3.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_4.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_5.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_6.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_7.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_8.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:24 test_9.log
[ec2-user@ip-172-31-0-70 tmp0]$ 
[ec2-user@ip-172-31-0-70 tmp0]$ 
[ec2-user@ip-172-31-0-70 tmp0]$ bash -x ./myscript.sh 
++ wc -l
++ ls -lah ./test_12.log ./test_13.log ./test_14.log ./test_15.log ./test_16.log ./test_17.log ./test_18.log ./test_19.log ./test_1.log ./test_20.log ./test_2.log ./test_3.log ./test_4.log ./test_5.log ./test_6.log ./test_7.log ./test_8.log ./test_9.log
+ TOTAL=18
+ let TOTAL--
+ COUNT=0
+ [[ 0 < 17 ]]
++ head -n 1
++ grep .log
++ grep -v .gz
++ ls -1
+ gzip test_12.log
+ let COUNT++
+ echo '17 - 1 = 16'
17 - 1 = 16
+ sleep 2
+ [[ 1 < 17 ]]
++ head -n 1
++ grep .log
++ grep -v .gz
++ ls -1
+ gzip test_13.log
+ let COUNT++
+ echo '17 - 2 = 15'
17 - 2 = 15
+ sleep 2
+ [[ 2 < 17 ]]
[ec2-user@ip-172-31-0-70 tmp0]$ 

您可以看到它在 2 小于 17 时停止。但是,如果在设置 tmp0 目录时,您只触摸 1 到 9 而不是两位数,则 while 循环会一直运行:

[ec2-user@ip-172-31-0-70 tmp0]$ rm test*
[ec2-user@ip-172-31-0-70 tmp0]$ ll
total 4
-rwxrwxr-x 1 ec2-user ec2-user 245 Aug  9 11:45 myscript.sh
[ec2-user@ip-172-31-0-70 tmp0]$ touch test_{1..9}.log
[ec2-user@ip-172-31-0-70 tmp0]$ ll
total 4
-rwxrwxr-x 1 ec2-user ec2-user 245 Aug  9 11:45 myscript.sh
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:28 test_1.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:28 test_2.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:28 test_3.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:28 test_4.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:28 test_5.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:28 test_6.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:28 test_7.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:28 test_8.log
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:28 test_9.log
[ec2-user@ip-172-31-0-70 tmp0]$ bash -x ./myscript.sh 
++ wc -l
++ ls -lah ./test_1.log ./test_2.log ./test_3.log ./test_4.log ./test_5.log ./test_6.log ./test_7.log ./test_8.log ./test_9.log
+ TOTAL=9
+ let TOTAL--
+ COUNT=0
+ [[ 0 < 8 ]]
++ head -n 1
++ grep .log
++ grep -v .gz
++ ls -1
+ gzip test_1.log
+ let COUNT++
+ echo '8 - 1 = 7'
8 - 1 = 7
+ sleep 2
+ [[ 1 < 8 ]]
++ head -n 1
++ grep .log
++ grep -v .gz
++ ls -1
+ gzip test_2.log
+ let COUNT++
+ echo '8 - 2 = 6'
8 - 2 = 6
+ sleep 2
+ [[ 2 < 8 ]]
++ head -n 1
++ grep .log
++ grep -v .gz
++ ls -1
+ gzip test_3.log
+ let COUNT++
+ echo '8 - 3 = 5'
8 - 3 = 5
+ sleep 2
+ [[ 3 < 8 ]]
++ head -n 1
++ grep .log
++ grep -v .gz
++ ls -1
+ gzip test_4.log
+ let COUNT++
+ echo '8 - 4 = 4'
8 - 4 = 4
+ sleep 2
+ [[ 4 < 8 ]]
++ head -n 1
++ grep .log
++ grep -v .gz
++ ls -1
+ gzip test_5.log
+ let COUNT++
+ echo '8 - 5 = 3'
8 - 5 = 3
+ sleep 2
+ [[ 5 < 8 ]]
++ head -n 1
++ grep .log
++ grep -v .gz
++ ls -1
+ gzip test_6.log
+ let COUNT++
+ echo '8 - 6 = 2'
8 - 6 = 2
+ sleep 2
+ [[ 6 < 8 ]]
++ head -n 1
++ grep .log
++ grep -v .gz
++ ls -1
+ gzip test_7.log
+ let COUNT++
+ echo '8 - 7 = 1'
8 - 7 = 1
+ sleep 2
+ [[ 7 < 8 ]]
++ head -n 1
++ grep .log
++ grep -v .gz
++ ls -1
+ gzip test_8.log
+ let COUNT++
+ echo '8 - 8 = 0'
8 - 8 = 0
+ sleep 2
+ [[ 8 < 8 ]]
[ec2-user@ip-172-31-0-70 tmp0]$ ll
total 36
-rwxrwxr-x 1 ec2-user ec2-user 245 Aug  9 11:45 myscript.sh
-rw-rw-r-- 1 ec2-user ec2-user  31 Aug  9 12:28 test_1.log.gz
-rw-rw-r-- 1 ec2-user ec2-user  31 Aug  9 12:28 test_2.log.gz
-rw-rw-r-- 1 ec2-user ec2-user  31 Aug  9 12:28 test_3.log.gz
-rw-rw-r-- 1 ec2-user ec2-user  31 Aug  9 12:28 test_4.log.gz
-rw-rw-r-- 1 ec2-user ec2-user  31 Aug  9 12:28 test_5.log.gz
-rw-rw-r-- 1 ec2-user ec2-user  31 Aug  9 12:28 test_6.log.gz
-rw-rw-r-- 1 ec2-user ec2-user  31 Aug  9 12:28 test_7.log.gz
-rw-rw-r-- 1 ec2-user ec2-user  31 Aug  9 12:28 test_8.log.gz
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:28 test_9.log
[ec2-user@ip-172-31-0-70 tmp0]$ bash -x ./myscript.sh 
++ wc -l
++ ls -lah ./test_9.log
+ TOTAL=1
+ let TOTAL--
+ COUNT=0
+ [[ 0 < 0 ]]
[ec2-user@ip-172-31-0-70 tmp0]$ ll
total 36
-rwxrwxr-x 1 ec2-user ec2-user 245 Aug  9 11:45 myscript.sh
-rw-rw-r-- 1 ec2-user ec2-user  31 Aug  9 12:28 test_1.log.gz
-rw-rw-r-- 1 ec2-user ec2-user  31 Aug  9 12:28 test_2.log.gz
-rw-rw-r-- 1 ec2-user ec2-user  31 Aug  9 12:28 test_3.log.gz
-rw-rw-r-- 1 ec2-user ec2-user  31 Aug  9 12:28 test_4.log.gz
-rw-rw-r-- 1 ec2-user ec2-user  31 Aug  9 12:28 test_5.log.gz
-rw-rw-r-- 1 ec2-user ec2-user  31 Aug  9 12:28 test_6.log.gz
-rw-rw-r-- 1 ec2-user ec2-user  31 Aug  9 12:28 test_7.log.gz
-rw-rw-r-- 1 ec2-user ec2-user  31 Aug  9 12:28 test_8.log.gz
-rw-rw-r-- 1 ec2-user ec2-user   0 Aug  9 12:28 test_9.log
[ec2-user@ip-172-31-0-70 tmp0]$ 

我只是想知道为什么。我敢肯定这可能是愚蠢的简单,但我只是没有看到它。起初我以为是因为 macOS 上的 bash “特别”,但后来我在 Amazon Linux 上尝试了它,并且遇到了同样的事情。

提前致谢。

【问题讨论】:

  • [[ $count &lt; $total ]] 是比较字符串的 ASCII 值,所以 10 小于 2。使用(( count &lt; total ))[[ $count -lt $total ]][ "$count" -lt "$total" ]
  • 谢谢@CharlesDuffy。我很抱歉没有做更好的搜索工作。我确实搜索过,但显然不是正确的术语。

标签: bash loops while-loop


【解决方案1】:

你正在做字符串比较。

[[ '2' > '19' ]] && echo "true"

会输出

true

使用整数算术。

(( 2 > 19 )) && echo "true"

不会输出任何东西。

【讨论】:

  • How to Answer 中,请参阅“回答正确提出的问题”部分,尤其是关于“之前已经多次提出并回答”的问题的要点。
  • 我同意,我敢肯定。不过,我不知道哪个问题是重复的,而且我不确定要搜索什么才能找到它。我尽最大努力进行谷歌搜索,前 3 个结果不是我想要重复的结果。那时,这需要 30 秒来编写,并且比找到要链接到的正确问题更快地回答问题
  • 我明白,但是将某人指向最完整的答案对于长期质量而言比快速/首先更好。 (也就是说,我有时会养成添加社区 wiki 答案的习惯,因为我知道某些内容是重复的,但可以快速得出一个快速的解决方案,并在花时间找到一个好的列表后几分钟后关闭为骗子; community-wiki 意味着允许并鼓励其他人编辑该答案以针对个人 OP 进行调整,而规范答案列表将其他有类似问题的人指向更完整和规范的来源)。
  • @CharlesDuffy,所以在未来,最好“放弃”我找不到链接的问题,留下基本上回答问题的评论,还是提供答案?如果我是新用户,链接到一个我合理地不知道如何搜索并将我的问题标记为重复的问题会很烦人,尤其是(我相信)它在 SO 中算作“坏问题”,而且它如果你有记录,威胁要暂停你的工作。当我第一次加入时,有几个问题发生在我身上。
  • @CharlesDuffy,我会牢记社区 wiki 选项,这样我就不会在寻找积分。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-10
相关资源
最近更新 更多