【问题标题】:While loop resets a numeric variable in a Bash script [duplicate]While循环重置Bash脚本中的数字变量[重复]
【发布时间】:2014-03-31 10:03:29
【问题描述】:

我正在尝试做一个简单的 bash 脚本来在一组文件夹中的每个文件中执行一些操作。我也喜欢统计脚本读取了多少文件,但是当脚本通过循环时,数值变量会被重置。

我使用的代码是这样的

#!/bin/bash
let AUX=0
find . -type "f" -name "*.mp3" | while read FILE; do
    ### DO SOMETHING with $FILE###
    let AUX=AUX+1
    echo $AUX
done
echo $AUX

我可以看到 AUX 在循环内计数,但最后一个“echo”打印一个 0,并且变量似乎真的被重置了。我的控制台输出是这样的

...
$ 865
$ 866
$ 867
$ 868
$ 0

我想在 AUX 中保留已处理的文件数。有什么想法吗?

【问题讨论】:

  • 这是 BashFAQ #24:mywiki.wooledge.org/BashFAQ/024
  • ...此外,作为与最佳实践相关的一项措施,对既不导出到环境也不导出到 shell 内置的变量名使用小写字母会更安全;这样你就可以避免命名冲突。

标签: bash loops while-loop


【解决方案1】:

不要使用管道,它会创建一个子shell。下面的例子。

#!/bin/bash
declare -i AUX=0
while IFS='' read -r -d '' file; do
    ### DO SOMETHING with $file###
    (( ++AUX ))
    echo $AUX
done < <(find . -type "f" -name "*.mp3")
echo $AUX

【讨论】:

  • 如果你想展示最佳实践,我建议find ... -print0while IFS='' read -r -d '' file;这样,代码可以正确处理包含换行符和反斜杠转义序列的名称(read 没有 -r 将被解释)。
  • ...虽然它是无害的,只要AUX 是一个数字,一般来说,echo $AUX 是个坏主意——例如,如果AUX=* 会列出文件在当前目录中。最好echo "$AUX"
【解决方案2】:

如果您有bash 4.0 或更高版本,请使用globstar 选项而不是find

shopt -s globstar
aux=0
for f in **/*.mp3; do
    # Just in case there is a directory name ending in '.mp3'
    [[ -f $f ]] || continue
    # Do something with $f
    echo "$(( ++aux ))"
done

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-05
    • 2018-02-15
    • 1970-01-01
    • 2020-11-11
    • 2013-08-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多