2012-09-20 51 views
1

过去几周我花了很多时间在这里发布。我终于认为我与学习bash的关系更加密切,但是我的代码有一个问题,我不能为我的生活弄清楚为什么它不会运行。我可以在终端中运行每一行,并返回一个结果,但由于某种原因,当我指出它运行时,它什么都不会做。我得到一个语法错误:意外的词(期待“做”)。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 

我错过了什么?

+2

你'ls'命令被作为一个荣耀的回声 - 假设它在所有工作,这它可能不会在'“$ image”'和'* .jpg'之间没有'/'。只需在'$ image“/ *。jpg中输入'f'; do'。而且,'--printf ='和''%s''之间会有一个额外的空间,这会破坏你的'stat'命令。 –

+1

@sean解释你的意思请 –

+1

@CuriousGeorge你已经在StackOverflow上提出了5个其他问题,并且从未将其中一个答复标记为答案。 –

回答

0

您的循环中缺失值的列表来遍历:

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 
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命令位于子外壳中;周围的脚本(包括重定向到results.txt)仍然在你开始任何目录。

现在,我们在目录中,我们可以随便找*.jpg,没有目录前缀,并且不需要调用basename上任何东西。

使用let((==))对待大小值为数字,而不是字符串,所以在方式,我们将不会绊倒任何wonkiness stat选择格式化值。

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

+0

当我做CD桌面/ epubs我按enter键。路径是正确的,我尝试在上面的脚本sh test.sh。我返回三个错误。两个是:找不到:debug.sh:另一个是debug.sh 6:debug.sh:语法错误:单词意外)期待“做”)。该消息也显示在我上面的旧脚本中。 –

+0

'sh'和'bash'是两个不同的shell(即使它们是相同的程序)。这个脚本必须用bash运行,而不是sh。 –

+0

我的歉意我还是这个新手。你指的是如何在终端中运行.sh文件?由于./filename与sh filename.sh相关? –

1

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

另外,不要迭代ls的输出。用匹配右壳:

出现
for f in "$file"/*.jpg ; do