1

过去几周我花了很多时间在这里发帖。我终于认为我在学习 bash 方面更接近了,但我的代码有一个问题,我一生都无法弄清楚为什么它不会运行。我可以在终端中运行每一行并返回一个结果,但由于某种原因,当我指向它运行时,它什么也不做。我得到一个语法错误:单词意外(期待“做”)。

#!/bin/bash

image="/Home/Desktop/epubs/images"

for f in $(ls "$image"*.jpg); do
    fsize=$(stat --printf= '%s' "$f");
    if [ "$fsize" -eq "40318" ]; then
       echo "$(basename $f)" >> results.txt
    fi
done

我错过了什么???

4

3 回答 3

1

问题可能出在行尾。确保您的脚本文件具有 unix 行结尾,而不是 Windows 行结尾。

此外,不要迭代ls. 在 shell 中使用 globbing:

for f in "$file"/*.jpg ; do
于 2012-09-20T20:12:56.810 回答
0

这就是我将如何做到的。

#!/bin/bash -e

image="/Home/Desktop/epubs/images"

(cd "$image" 
 for f in *.jpg; do
   let fsize=$(stat -c %s "$f")
   if (( fsize == 40318 )); then
     echo "$f"
   fi
 done) >results.txt

-e意味着如果出现任何问题,脚本将退出(例如,无法 cd 进入目录)。当您对该行为感到满意时,可以节省大量错误检查。

括号表示cd命令在子shell中;周围的脚本(包括重定向到results.txt)仍然在您开始的任何目录中。

现在我们在目录中,我们可以只查找*.jpg,没有目录前缀,也不需要调用basename任何东西。

使用let并将(( == ))size 值视为数字而不是字符串,因此我们不会因stat选择格式化值的方式而被任何不稳定所绊倒。

我们只是将整个循环的输出重定向到结果文件中,而不是每次都追加;它更有效。如果您有results.txt想要保留的现有内容,您只需将>back 更改为 a >>,但将其留在整个循环中仍然比打开文件并在每次迭代时附加到它更有效。

于 2012-09-20T20:10:30.120 回答
0

您的 for 循环似乎缺少要迭代的值列表:

image="/Home/Desktop/epubs/images"
for f in $(ls "$image"*.jpg); do

因为$image不以 / 结尾,所以您的ls命令扩展为

for f in $(ls /Home/Desktop/epubs/images*.jpg); do

这可能导致

for f in ; do

导致语法错误。最简单的解决方法是

for f in $(ls "$image"/*.jpg); do

但是您应该接受其他答案中的建议并跳过ls

for f in "$image"/*.jpg; do
于 2012-09-20T20:17:26.083 回答