如果我有2个文件file1
,file2
,我是否可以安全地在bash中对它们进行同步,以使file1
或file2
之一为输出文件以及输入?
例如:
$ cat file1 file2 >> file2
产地:
$ cat: file2: input file is output file
我想这意味着我所做的不是“安全”。
这也让我感到惊讶 - 猫如何知道file2
“运营商之后的>>
”。这里的第二个问题是>>
如何在bash中工作?它是否在将数据“重定向/保存”到操作员后面的文件之前将数据存储在临时位置?
答案 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"