带有重定向的linux uniq命令出错

带有重定向的linux uniq命令出错,linux,shell,command-line-interface,io-redirection,uniq,Linux,Shell,Command Line Interface,Io Redirection,Uniq,我刚开始学习Linux cli,遇到了一个有趣的问题 我创建了一个1.txt文件,例如: 1 1 2 2 3 当我使用uniq1.txt时,它会发出123。我决定将这个结果输出到1.txt,因此这个小技巧将删除文件中所有重复的元素并保存它。为此,我使用了以下命令:uniq 1.txt>1.txt。但最后它显示1.txt文件是完全空的。有人能帮我理解发生了什么吗?通常在bash中,您应该避免管道传输到前面命令中使用的文件。管道(来自)通常与命令(在本例中为uniq)并行工作,因此可能会发生意外行

我刚开始学习Linux cli,遇到了一个有趣的问题

我创建了一个1.txt文件,例如:

1
1
2
2
3

当我使用
uniq1.txt
时,它会发出
123
。我决定将这个结果输出到
1.txt
,因此这个小技巧将删除文件中所有重复的元素并保存它。为此,我使用了以下命令:
uniq 1.txt>1.txt
。但最后它显示
1.txt
文件是完全空的。有人能帮我理解发生了什么吗?

通常在
bash
中,您应该避免管道传输到前面命令中使用的文件。管道(来自
)通常与命令(在本例中为
uniq
)并行工作,因此可能会发生意外行为。一些命令,如
sed
perl
具有类似
-i
的选项,允许就地文件操作,但通常认为不允许这样做是最安全的。肮脏的解决办法是这样的:

uniq 1.txt > tmpfile
mv tmpfile 1.txt

这不仅仅是uniq,所有命令都是这样运行的;重定向会在所有内容之前启动,因此会在内容被读取之前擦除内容。请标记重复内容,而不是回答重复内容;请参阅的“回答问题”部分的第三个要点。重定向到现有问题的部分价值在于,这些问题的答案已经过正确性审查、评论和投票等。正如目前所写的,这个答案是不正确的:在一个简单的命令中,例如
foo>bar
foo
仅在连接到其标准输出的
bar
打开后启动。因此,重定向不是“并行的”(因此受制于可能赢或输的竞争条件);重定向(截断输出文件)在100%的时间内首先发生。(在其他一些情况下,您可能会有一个竞争——在
foo baz | bar>baz
中,一些shell可能会为
foo
的stdout创建一个FIFO,启动
foo
,并行打开
baz
进行输出,截断它,然后在
baz
打开后——用FIFO的另一侧运行
bar
)附加到stdin;在这种情况下,
foo
在启动
bar
之前,不太可能但理论上可能读取一些原始文件内容;但是,在
uniq 1.txt>1.txt
中不存在这种竞争条件,在这种情况下,文件总是在读取之前被截断)。