【问题标题】:for loop in bash just runs oncebash 中的 for 循环只运行一次
【发布时间】:2016-10-27 02:49:31
【问题描述】:

我正在 bash 中进行分辨率检查,但这个循环只运行一次并且没有错误地结束:

for file in *; do \
  WIDTH = $(identify -ping -format '%h' $file) \
  HEIGHT = $(identify -ping -format '%w' $file) \
  if [ "$WIDTH" -ge 500 ]; then \
    echo width greater than 500 \
  elif ["HEIGHT" -ge 500]; then \
    echo height greater than 500 \
  fi \
done

输出

height greater than 500 fi done

为什么不检查所有文件?

【问题讨论】:

  • 有多少个文件?您是否检查过它是否在您认为的目录中工作?
  • 12000+ 个文件,用ls -al检查。
  • 这里的反斜杠实际上是错误的。
  • 作业中的空格也是如此。通过shellcheck.net 运行您的代码

标签: bash macos


【解决方案1】:
#!/bin/bash
# using bash, not sh, ensures that <(), (( )), and other extensions are available.

for file in *; do
  IFS=: read -r width height < <(identify -ping -format '%w:%h\n' "$file")
  if (( width >= 500 )); then
    printf '%s\n' "$file has width greater than 500"
  elif (( height >= 500 )); then
    printf '%s\n' "$file has height greater than 500"
  fi
done

  • 运行identify 两次会使调用外部命令的性能影响加倍;最好只运行一次,并一次读取两个变量。用于将identify 命令的输出收集到流中的语法是process substitution,而read 命令在BashFAQ #001the relevant bash-hackers wiki page 中有相当全面的讨论。
  • 反斜杠是行继续;当您有一个跨越多行的简单命令(不是像这样的复合命令)时,它们是合适的。在这种情况下,他们完全错了。
  • [ 是一个命令,命令名称和参数之间需要用空格隔开。正如你运行ls -l,而不是ls-l,你不能运行[foo;它必须是[ foo,作为两个单独的词。 (如果更清楚,可以考虑使用同义词testif test "$width" -ge 500; then ...)。
  • 全大写变量名被指定为by POSIX-defined convention 用于对系统和shell 有意义的名称,而具有至少一个小写字符的名称保留供应用程序使用。 (该约定明确适用于环境变量,但 shell 变量共享相同的命名空间:设置名称与环境变量重叠的 shell 变量将覆盖后者)。
  • 使用printf 而不是echo 具有更好的定义行为:the POSIX specification for echo 留下了广泛的未定义行为,如果打印包含文字反斜杠的文件名,echo 的行为将变得依赖于实现,因此不可移植.请特别参阅链接页面的应用程序使用部分。
  • 使用(( )) 会将您带入数学上下文,其中可以使用不带$ 的变量名,并且可以使用更自然的C 风格数学语法,例如&gt;= 而不是-ge。 (这是一种 bashism —— POSIX sh 仅指定 $(( )),它具有类似的行为,但是是一个替换命令;因此,在 POSIX sh 中,可以改为编写 if [ "$(( width &gt;= 500 ? 1 : 0))" = 1 ] 来测试此替换的结果。

【讨论】:

  • 太棒了,感谢您的详细解释。直到。 :)
【解决方案2】:

问得太早了,我自己用这个很棒的助手解决了这个问题 - shellcheck

for file in *; do 
  WIDTH=$(identify -ping -format '%h' "$file") 
  HEIGHT=$(identify -ping -format '%w' "$file") 
  if [ "$WIDTH" -ge 500 ]; then 
    echo width greater than 500 
  elif [ "$HEIGHT" -ge 500 ]; then 
    echo height greater than 500 
  fi 
done

【讨论】:

  • 顺便说一句,运行identify 两次效率相当低——您可以从一次调用中读取两个变量。我将编辑我的答案以进行演示。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-15
  • 2014-12-07
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
  • 2022-10-14
相关资源
最近更新 更多