Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
bash脚本:在输出也是输入的情况下连接两个文件的安全方法?_Bash_File_Concatenation - Fatal编程技术网

bash脚本:在输出也是输入的情况下连接两个文件的安全方法?

bash脚本:在输出也是输入的情况下连接两个文件的安全方法?,bash,file,concatenation,Bash,File,Concatenation,如果我有两个文件file1,file2,我可以在bash中以安全的方式将它们关联起来,使file1或file2中的一个既是输出文件又是输入文件吗 例如: $ cat file1 file2 >> file2 $ printf 'one\ntwo\n' >foo $ printf 'three\nfour\n' >bar $ sed -i '' '$rbar' foo $ cat foo one two three four 产生: $ cat: file2: inpu

如果我有两个文件
file1
file2
,我可以在bash中以安全的方式将它们关联起来,使
file1
file2
中的一个既是输出文件又是输入文件吗

例如:

$ cat file1 file2 >> file2
$ printf 'one\ntwo\n' >foo
$ printf 'three\nfour\n' >bar
$ sed -i '' '$rbar' foo
$ cat foo
one
two
three
four
产生:

$ cat: file2: input file is output file
我想这意味着我所做的不是“安全的”

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

~$ 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的printf:

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

$printf“%s\n%s\n”“$”(正确的解决方案是使用临时文件

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

$ cat file1 file2 >> file2
$ 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选项。

解决方法 以下内容可安全解决您的问题:

cat file1 <(dd if=file2 bs="$(wc -c <file2)" count=1) >> file2
cat文件1>file2
解释 如果
cat
在这里没有保护措施(有些实现没有!),您将有一个无休止的循环-
文件2
中将永远有更多的信息(因为
cat
自己的输出被附加到它),因此附加操作将永远不会停止

dd if=file2 bs=SIZE\u OF_file2 count=1
仅在命令启动时发出
file2
中存在的字节数,因此它避免了这种无休止的循环。此外,由于
cat
正在从进程替换中读取,因此它无法检测到
file2
是内容的源,所以它会这样做esn不会触发错误。

使用临时文件:

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

您不能附加到正在读取的文件。输出到第三个文件,然后将第三个文件
mv
添加到第二个文件。
>
不会写入缓冲区;它会写入一个文件,因此需要一个新文件来转储
cat
输出。Linux都是基于文件的。如果您想安装,可以从moreutils包获得帮助l一个附加包。外壳在启动
cat
之前打开
file2
进行输出,但是
cat
完全能够检查其标准输出并告诉(1)它是否是文件,以及(2)它是哪个文件。@glennjackman,即使存在
海绵-a
,但如果我们谈论的是一个大文件,它的操作成本要高得多,因为它从一开始就重写输出文件,而不是只从附加点写入。OP使用的是
,而不是
。因此没有截断操作。这就是说--我认为你把它误认为是OP错误的一个更常见的变体。你最好引用
”$(这适用于短文件。如果我们处理的是兆字节或千兆字节…我还没有测试过,但该命令行真的能工作吗?在我的系统上,
wc-c file2
包含文件名。关于无休止循环的观点很好。作为参考,你可以“欺骗”猫(为了科学!)通过在子shell中运行它,使其最终输出不可检测:
(cat foo bar)>bar
。在我的测试中,这产生了一个
bar
,其中包含
foo
的重复内容,没有原始
bar
@ghoti的迹象,….我很惊讶它能起作用——给定的重定向是在调用
cat
的shell启动之前执行的,而不是在shell启动之前执行的
cat
,对从
cat
的启动中内省传递到stdout上的文件描述符的检测过程没有任何影响(我希望如此)。您确定您是在一个首先可以进行检测的平台上进行测试的吗?(例如,在MacOS的
cat
中不可用)@ghoti,…并在MacOS上运行GNU
cat
,检测似乎仍然有效:
$(gcat file1 file2)>>file2
gcat:file2:input file is output file
@ghoti,…现在,什么可以绕过检测(但可能会产生一个无休止的输出文件,这取决于file2的大小和竞争的结果)是
cat file1>file2