我知道这三个函数的原理。以及为什么cat < file > file
会清除文件内容。但我不明白为什么它cat < file >> file
不是将内容写入两次,而是像在无限 while 循环中一样将内容连接起来。
答案1
好吧,我的cat
(在 Kubuntu 中)说完input file is output file
就退出了。我知道你cat
不那么聪明(或者不那么懒惰)。
您所观察到的现象很容易解释。cat
读取和写入都是分块进行的。假设第一个块未到达文件末尾 (EOF),并且其内容在同一文件的末尾连接起来。读取cat
前进了一定数量的字节,但文件末尾“偏离”了相同的数量。实际上,cat
它再次与开始时一样远离 EOF。并且它一直持续下去。
就好像你每跑100米,终点线就会离你多100米。你永远也到不了终点,而跑过的距离会无止境地增长。
除非原来的距离为 100 米或更短。在这种情况下,你会在终点线重新定位之前到达终点线。类似地cat
可能如果文件足够小,则完成,但我对此表示怀疑。我期望cat
只有当它尝试再次读取并且能够读取 0 个字节时,它才“知道”它已经到达了 EOF,不能再读取了。这意味着它在上一步中已经读取到 EOF,此时它读取了超过 0 个字节。但在你的情况下,如果它在上一步中读取了超过 0 个字节,那么文件会立即增大,并且仍然有数据要读取。
我预测有两种情况会让你cat
停止:
- 当文件为空(0字节长度)时,
- 当文件不存在并且您更改重定向的顺序时(即将
cat >> file < file
会工作,cat < file >> file
将会抛出错误;这是因为重定向是从左到右“提供”的,>>
如果需要则会创建文件,<
要求文件存在)。
一般来说,在单个命令中使用带有 stdin 和 stdout(或/和 stderr)重定向的同一文件会带来麻烦。不过,如果你需要这样做,sponge
公用事业(例如在moreutils
Ubuntu、Debian 的软件包中)。
sponge
读取标准输入并将其写入指定文件。与 shell 重定向不同,sponge 会在打开输出文件之前吸收所有输入。这允许限制从同一文件读取和写入的管道。如果没有指定输出文件,
sponge
则输出到标准输出。
而不是cat < file >> file
运行sponge < file >> file
。它将执行您期望的操作cat
(我认为,除非文件足够大,以至于在被吸收时耗尽您的资源)。
另一种方法是< file cat | cat >> file
。由于两个cat
-s 之间的缓冲,第一个 -s 会在第二个 -s 扩展文件之前真正到达 EOF 并退出,如果文件足够小。从一个小文件(但不为空)开始重复此命令几次,文件最终会变得足够大,使命令的行为就像使用一个的原始命令一样cat
。注意< file cat | unbuffer cat >> file
即使对于非常小的文件也会摆脱缓冲区和循环。
答案2
嗯,基本上它的工作原理如下:
>
用于覆盖文件的内容。例如:echo "HELLO WORLD" > file.txt
。
>>
用于将内容附加到文件。例如:echo "New line" >> file.txt
。
<
您可以使用文件作为输入并重定向到另一个文件。例如:cat < file.txt > file2.txt
。一个实际的例子是ftp myftpbox.com < commands.txt
,这将连接到 FTP 并执行文件中的命令列表commands.txt
。
笔记:使用时要小心,>
因为您可以在没有任何确认的情况下覆盖现有文件,您可以通过运行来改变它set -o noclobber
。
我希望这有帮助。