1

我写了一个 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
4

3 回答 3

2

重定向到源文件会损坏它。而是重定向到一个临时文件,然后重命名它。

于 2013-05-30T11:41:02.700 回答
0

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

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

外壳发现了> $artists/$file. tail它会在运行程序之前将文件截断为零字节。根据事件的确切顺序,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)。如果失败,您可能还会考虑是否要跳出循环或退出程序。

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

于 2013-05-30T12:14:13.790 回答
0

重定向到源文件将在下一个命令读取文件之前截断文件。既然你提到了,你不能创建临时文件,那么创建命名管道怎么样。

您可以像文件一样重定向和读取管道。另外,您可以并行执行此操作。

于 2013-05-30T13:12:39.980 回答