![为什么这个函数不能用于吸收标准输入?](https://linux22.com/image/219656/%E4%B8%BA%E4%BB%80%E4%B9%88%E8%BF%99%E4%B8%AA%E5%87%BD%E6%95%B0%E4%B8%8D%E8%83%BD%E7%94%A8%E4%BA%8E%E5%90%B8%E6%94%B6%E6%A0%87%E5%87%86%E8%BE%93%E5%85%A5%EF%BC%9F.png)
这:
echo 'some text' > file.txt
cat file.txt > file.txt
显然给了我一个空文件。
但也令我惊讶的是:
cat2 () {
cat "$@" > tmp.txt
cat tmp.txt
return $?
}
echo 'some text' > file.txt
cat2 file.txt > file.txt
它给了我一个空文件,即使该文件tmp.txt
已被删除,与file.txt
.
这个方法也行不通!:
echo 'some text' > file.txt
cat file.txt | cat2 > file.txt
为什么文件还是被清空了?
答案1
你的命令
cat2 file.txt > file.txt
将创建一个新的空file.txt
前它调用该cat2
函数。
因此,在运行时,cat2
文件是空的,因此cat
它将导致空输出。
如果它有助于打破操作顺序,那么您所做的是
- 创建一个包含内容的文件 file.txt
- 创建一个新的空白文件file.txt
- 运行 cat2 并输出到 file.txt
这是因为重定向运算符发生在cat2
执行之前。
答案2
这个构造确实有效(它用作tr
示例操作):
{ 'rm' -f File.txt && tr '[:lower:]' '[:upper:]' > File.txt; } < File.txt
输入重定向< File.txt
首先将文件作为标准输入分配给大括号中的语句,然后再执行块中的任何内容。
删除块内的文件不会删除内容,因为该文件有一个打开的文件描述符。请注意,rm
引号是为了避免可能出现别名的情况,例如使用-i
选项。
输出重定向创建一个与原始文件同名的新输出文件(inode)。当tr
终止时,新文件被关闭。
最后,输入重定向完成,它现在没有通过目录或文件描述符的连接,并且它的资源被释放。
根据 Stéphane Chazelas 的精彩评论进行编辑:
(a) 应rm
具有-f
避免所有提示和错误的选项。
(b)tr
应使用与区域设置无关的字符类。
(c) 新的 File.txt 与旧的 File.txt 独立,具有不同的索引节点号、诞生时间以及可能的所有权、权限、acl 或其他扩展属性。它还用普通文件替换符号链接,并分离硬链接,将原始数据保留在不同的路径名下。