为什么这个函数不能用于吸收标准输入?

为什么这个函数不能用于吸收标准输入?

这:

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 或其他扩展属性。它还用普通文件替换符号链接,并分离硬链接,将原始数据保留在不同的路径名下。

相关内容