“确保不要在同一管道中读取和写入同一文件”

“确保不要在同一管道中读取和写入同一文件”

shellcheck 报告:

echo -e "blah/blah\n$(cat "$tmpdir"/"$filename".jpdf)" > "$tmpdir"/"$filename".jpdf
                          ^-- SC2094: Make sure not to read and write the same file in the same pipeline.
                                                         ^-- SC2094: Make sure not to read and write the same file in the same pipeline.

blah/blah该命令的目的是在文件的开头插入一行"$tmpdir"/"$filename".jpdf

“确保不在同一管道中读取和写入同一文件”是什么意思?

我该怎么办呢?

谢谢。

答案1

正如其他答案所指出的,它警告您读取和写入同一文件将擦除该文件。原因是这>会导致文件在输入完成之前被截断。

你有两个选择,

  1. sponge从包装中取出使用moreutilssponge确保输入在通过管道传送到下一个命令之前被完全消耗。

    代替

    command "$file" > "$file"
    

    command "$file" | sponge "$file"
    
  2. 将输出重定向到另一个文件,然后重命名。

    像这样

    command "$file" > "$file2" && mv "$file2" "$file"
    

关于您的具体问题:在文件中添加“blah/blah”,sed如果它支持该-i选项,则可以使用。举GNU sed个例子:

sed '1i\
blah/blah' -i "$file"

答案2

它的意思正是它在最字面意义上所说的。该命令实际上所做的是覆盖文件$tmpdir/$filename.jpdf,仅回显单行。 shell 将看到重定向,然后截断该文件并打开它进行写入,然后它才会开始执行命令以生成其(新)内容。您应该做的是将新内容写入不同的文件,然后在第二个命令中将新文件复制到旧名称。

答案3

让我们输入一个等效的更简单的命令行:

cat file > file

如果文件包含数据,它将被删除,让我们尝试:

$ echo "content of file" > file
$ cat file
content of file

$ cat file > file

$ cat file
                     # empty file.

shell 在执行命令之前处理重定向。
在处理时>file,它打开file以进行写入截断。
之后,该文件为空。
该命令cat执行空文件的 cat 操作,不会写入任何内容。

相关内容