我正在尝试执行以下操作
touch ~/scratches/scr6.txt | cat ~/scr.txt > ~/scratches/scr6.txt | cat /dev/null > ~/scr.txt
我不知道为什么 scr6.txt 总是空的,但是执行以下操作填充文件
cat ~/scr.txt > ~/scratches/scr6.txt
我想知道为什么第一个案例不起作用?
答案1
分解每个步骤:
touch ~/scratches/scr6.txt
如果文件存在,则将时间戳更新为现在。如果不存在,则创建它。
cat ~/scr.txt > ~/scratches/scr6.txt
读取 ~/scr.txt 并将内容写入 ~scratches/scr6.txt
cat /dev/null > ~/scr.txt
清空 ~/scr.txt 文件
正如评论中提到的,在命令之间使用“&&”(AND)而不是“|” (PIPE) 会更合适。
答案2
好的,考虑到该scr.txt
文件在执行命令之前包含一些文本并且scr6.txt
尚不存在:命令
touch ~/scratches/scr6.txt | cat ~/scr.txt > ~/scratches/scr6.txt | cat /dev/null > ~/scr.txt
- 空的
scr.txt
文件 (cat /dev/null > ~/scr.txt
) - 用(无)
scr6.txt
内容覆盖( )scr.txt
cat ~/scr.txt > ~/scratches/scr6.txt
- 不执行任何操作,因为
scr6.txt
已经存在 (touch ~/scratches/scr6.txt
)
但是下面的命令
cat ~/scr.txt > ~/scratches/scr6.txt
只需scr.txt
将内容写入scr6.txt
这就是为什么在第一种情况下两个文件都是空的,而在第二种情况下一切都按预期进行。
答案3
据我了解,管道进程或多或少都是同时启动的。通常,管道中的进程将从 stdin 读取或写入 stdout(或两者),并且 I/O 的完成将决定进程何时结束。
对于没有任何输出(例如touch
)或任何标准输入(例如cat
在文件上操作时)的进程,我通常希望程序会忽略它们的管道连接。
所以你基本上会得到三个并行运行的命令:
touch ~/scratches/scr6.txt
,
cat ~/scr.txt > ~/scratches/scr6.txt
, 和cat /dev/null > ~/scr.txt
。
如果 ~/scr.txt 尚不存在,命令 2 是否会失败并出现错误,这可能取决于操作系统,因为它将与命令 3 处于竞争条件。命令 1 和 2 也处于竞争条件,但race 只会影响文件的 ctime/mtime/atime。
答案4
简单来说:
该touch
命令是创建新的方式,空文件。它还用于更改现有文件和目录的时间戳(即最近访问和修改的日期和时间)。
在第一个命令中,它创建一个名为 的空文件scr6.txt
。
但在第二个命令中,它创建一个文件scr6.txt
并将所有内容写入scr.txt
该文件。