bash脚本:连接输出也是输入的2个文件的安全方法?

时间:2017-07-20 20:26:10

标签: bash file concatenation

如果我有2个文件file1file2,我是否可以安全地在bash中对它们进行同步,以使file1file2之一为输出文件以及输入?

例如:

$ cat file1 file2 >> file2

产地:

$ cat: file2: input file is output file

我想这意味着我所做的不是“安全”。

这也让我感到惊讶 - 猫如何知道file2“运营商之后的>>”。这里的第二个问题是>>如何在bash中工作?它是否在将数据“重定向/保存”到操作员后面的文件之前将数据存储在临时位置?

4 个答案:

答案 0 :(得分:3)

解决方法

以下安全适用于您的问题:

cat file1 <(dd if=file2 bs="$(wc -c <file2)" count=1) >> file2

解释

如果cat在这里没有安全措施(而某些实现没有!),那么你将有一个无限循环 - 在file2中永远会有更多信息(因为{ <1}}自己的输出被附加到它上面,因此追加操作永远不会停止。

cat仅发出dd if=file2 bs=SIZE_OF_FILE2 count=1 中的命令启动时的字节数,因此它避免了这种无限循环。此外,由于file2正在从进程替换中读取,因此它无法检测到cat是内容的来源,因此它不会使错误发生错误。

答案 1 :(得分:0)

~$ echo hello > f1
~$ echo world > f2

使用tmp文件:

~$ cat f1 f2 > tmp && cat tmp >> f1 && rm tmp
~$ cat f1
hello
hello
world

使用tee -a:

~$ cat f1 f2 | tee -a f1
hello
world
~$ cat f1
hello
hello
world

使用粘贴:

~$ paste -d"\n" f1 f2 >> f1
~$ cat f1
hello
hello
world

使用bash&lt; printf:

$ printf "%s\n%s\n" "$(<f1)"  "$(<f2)" >> f1
$ cat f1
hello
hello
world

答案 2 :(得分:0)

正确的解决方案是使用临时文件。

使用临时文件的一种方法是使用不可见的工具。 sed,例如:

$ printf 'one\ntwo\n' >foo
$ printf 'three\nfour\n' >bar
$ sed -i '' '$rbar' foo
$ cat foo
one
two
three
four

或者,模仿你在第一个例子中尝试做的事情:

$ printf 'one\ntwo\n' >foo
$ printf 'three\nfour\n' >bar
$ sed -i '' -e '$rbar' -e '$rbar' foo
$ cat foo
one
two
three
four
three
four

当然,您可以调整操作系统的sed选项。

答案 3 :(得分:0)

使用临时文件:

tmp=$(mktemp)
cat f2 f1 f2 > "$tmp" &&
  ln -f "$tmp" f2 &&
  rm "$tmp"