使用bash脚本的奇怪行为

时间:2013-05-30 11:35:57

标签: bash

我写了一个bash脚本,假设创建一些文件并写入它们。 无论如何,脚本的作用并不重要,事情是 - 代码中有一个注释(最后),它只是为了在屏幕上打印一些内容。如果我试图像那样运行它 - 程序不会在文件中写入输出,但是如果把这行不作为注释(即删除'##')那么它可以工作 - 程序将输出写入文件。 我非常努力,但我不明白发生了什么...... 如果你需要脚本的其余部分,或者对它所说的内容有更多的解释。

files=( `ls $artists` )
echo artists=%${files[*]}%
for file in ${files[*]}; do
    echo file= $file:
    lines=`wc -l $artists/$file | cut -d" " -f1`
    echo lines=$lines
    counter=0
    while read -a line; do
        if (( $counter==$lines ));then
            break;
        fi

        if [[ ! $line =~ [^[:space:]] ]] ; then
            continue
        fi
        rank=$(( ${line[3]}+$(( 5*${line[4]} )) ))
        echo  ${line[*]}
        echo rank = $rank
        echo  "${line[*]} $rank" >> $artists/$file
        let counter++
    done < $artists/$file

    ##cat  $artists/$file | tail -$lines
    cat $artists/$file | tail -$lines > $artists/$file
done

3 个答案:

答案 0 :(得分:2)

重定向到源文件会损坏它。改为重定向到临时文件,然后重命名。

答案 1 :(得分:0)

cat $artists/$file | tail -$lines > $artists/$file

让我们考虑一下这是做什么的。首先,您正在运行cat程序,这是不必要的。它可能会影响症状,但我对此表示怀疑。

shell发现了> $artists/$file。在运行tail程序之前,它会将文件TRUNCATE为零字节。根据事件的确切顺序,cat将读取空文件。

所以,不要那样做,试试这个:

if tail -$lines "$artists/$file" > "$artists/$file.$$"
then
    mv "$artists/$file.$$" "$artists/$file"
else
    echo "Unable to tail $artists/$file" >&2
fi

无需cat。我们重定向到一个附加了PID($$)的临时文件名。如果tail工作,那么我们将临时文件重命名为所需的文件名,否则我们将错误消息写入stderr(fd 2)。如果失败,您可能还会考虑是否要退出循环或退出程序。

防御性编程还要求我们将任何文件名变量放在双引号内,以防一些numpty在文件或目录名(Program Files)中放入空格。

答案 2 :(得分:0)

重定向到源文件将在下一个命令读取文件之前截断该文件。由于您提到过,您无法创建临时文件,如何创建命名管道

您可以像管文件一样重新定向和读取管道。另外,你可以并行完成。