Bash变量数学不起作用

时间:2011-06-09 22:39:25

标签: linux bash math variables

我有一个简单的bash脚本,它构成了我开发的内部Web应用程序的一部分。

目的是在用户删除原始图像时自动删除图像的缩略图。

该脚本将一些基本状态信息记录到文件/var/log/images.log

#!/bin/bash
cd $thumbpath
filecount=0
# Purge extraneous thumbs
find . -type f | while read file
do
  if [ ! -f "$imagepath/$file" ]
  then
    filecount=$[$filecount+1]
    rm -f "$file"
  fi
done
echo `date`: $filecount extraneous thumbs removed>>/var/log/images.log

虽然脚本正确地删除了拇指,但它没有正确输出正在清除的拇指数量,它始终显示0

例如,只需手动创建一些孤立的缩略图,然后运行我的脚本,就会删除手动生成的孤立拇指,但日志会显示:

  

Thu Jun 9 23:30:12 BST 2011:0删除了无关的拇指

如果文件 被删除,那么阻止$ filecounter显示非零数字的错误是什么?

我已经创建了以下bash脚本来测试它,这很有效,输出0然后1

#!/bin/bash
count=0
echo $count
count=$[$count+1]
echo $count

修改

感谢您的回答,但为什么以下工作

$ x=3
$ x=$[$x+1]
$ echo $x
4

...第二个例子也有效,但它在第一个脚本中不起作用吗?

第二次修改:

这有效

count=0
echo Initial Value $count
for i in `seq 1 5`
do
  count=$[$count+1]
  echo $count
done
echo Final Value $count


Initial Value 0
1
2
3
4
5
Final Value 5

count=$[$count+1]替换为count=$((count+1)),而不是在我的初始脚本中。

3 个答案:

答案 0 :(得分:6)

你使用的是错误的操作员。请尝试使用$(( ... )),例如:

$ x=4
$ y=$((x + 1))
$ echo $y
5
$

修改
你遇到的另一个问题是管道问题。之前碰到了这个(用ksh,但我不会惊讶地发现其他炮弹有同样的问题)。管道正在分支另一个bash进程,因此当你执行增量时,filcount会在管道之后分叉的子shell 中递增。由于子shell具有自己独立的环境(环境变量在被调用的进程中继承,但被调用的进程无法修改调用进程的环境),因此该值不会传递回调用shell。

作为一个例子,这表明filecount增加好了:

#!/bin/bash

filecount=0
ls /bin | while read x
do
        filecount=$((filecount + 1))
        echo $filecount
done
echo $filecount

...所以你应该看到循环中的filecount增加,但是最终的filecount将为零,因为这个echo属于主shell,但是分叉​​的子shell(纯粹由while循环组成)。

你可以获得价值的一种方法就是这样......

#!/bin/bash

filecount=0
filecount=`ls /bin | while read x
do
        filecount=$((filecount + 1))
        echo $filecount
done | tail -1`
echo $filecount

这只有在你不关心循环中的任何其他stdout输出时才会起作用,因为这会将它从我们输出的最后一行(filecount的最终值)抛出。这是有效的,因为我们使用stdout和stdin将数据反馈给父shell。

根据你的观点,这可能是一个令人讨厌的黑客或一个漂亮的shell jiggery-pokery。我会让你决定你的想法: - )

答案 1 :(得分:2)

如果将管道移除到while构造中,则删除bash创建子壳的需要。

改变这个:

filecount=0
find . -type f | while read file; do
  if [ ! -f "$imagepath/$file" ]; then
    filecount=$[$filecount+1]
    rm -f "$file"
  fi
done
echo $filecount

到此:

filecount=0
while read file; do
  if [ ! -f "$imagepath/$file" ]; then
    rm -f "$file" && (( filecount++ ))
  fi
done < <(find . -type f)
echo $filecount

由于最后隐藏了find命令,因此难以阅读。另一种可能性是:

files=$( find . -type f )
while ...; do
  : 
done <<< "$files"

答案 2 :(得分:1)

Chris J is quite right您使用了错误的运算符和POSIX子shell变量作用域意味着您无法以这种方式获得最终计数。

作为旁注,在进行数学运算时,您还可以考虑使用let shell bultin:

$ filecount=4
$ let filecount=$filecount+1
$ echo $filecount
5

此外,如果您希望范围尽可能像您预期的那样工作,尽管有管道,您可以使用zsh而不是bash。在这种情况下,它应该是替代品,并按预期工作。