我想添加一个运算符(例如^>)来处理prepend而不是append(>>)。我是否需要修改Bash源或是否有更简单的方法(插件等)?
答案 0 :(得分:3)
首先,你需要修改bash源并且非常重要。因为,最重要的是,您的^>
实际上很难实现。
请注意,bash重定向操作符通常执行非常简单的写操作,并且仅处理单个文件(或管道中的程序)。排除非常具体的解决方案,您通常无法写入文件的开头,原因很简单,您需要在每次写入后将所有剩余的内容向前移动。你可以尝试这样做,但它会很难,非常无效(因为每次写入都需要重写整个文件)并且非常不安全(因为任何错误你最终会随机混合旧的和新版本。)
那就是说,你可能会更好地使用一个函数或任何其他使用临时文件的解决方案,就像其他人建议的那样。
为了完整性,我自己实现了:
prepend() {
local tmp=$(tempfile)
if cat - "${1}" > "${tmp}"; then
mv "${tmp}" "${1}"
else
rm -f "${tmp}"
# some error reporting
fi
}
请注意,您不同于@jpa建议,您应该将连接数据写入临时文件,因为操作可能会失败,如果确实如此,您不希望丢失原始文件。之后,您只需用新文件替换旧文件,或者删除临时文件并以您喜欢的方式处理失败。
概要与其他解决方案相同:
echo test | prepend file.txt
还有一些修改后的版本可以保留权限并使用符号链接(如果有必要)安全地播放,例如>>
:
prepend() {
local tmp=$(tempfile)
if cat - "${1}" > "${tmp}"; then
cat "${tmp}" > "${1}"
rm -f "${tmp}"
else
rm -f "${tmp}"
# some error reporting
fi
}
请注意,此版本实际上不太安全,因为如果在第二个cat
期间其他内容会写入磁盘并填满,那么您最终会得到不完整的文件。
说实话,我不会亲自使用它,但如果需要,可以在外部处理符号链接和重置权限。
答案 1 :(得分:2)
^
是一个糟糕的角色选择,因为它已在history substitution中使用。
要向shell语法添加新的重定向类型,请从parse.y
开始。将其声明为新的%token
以便可以使用它,将其添加到STRING_INT_ALIST other_token_alist[]
以便它可以出现在输出中(例如错误消息),更新解析器中的redirection
规则,并在遇到相应的字符时更新词法分析器以发出此标记。
command.h
包含enum r_instruction
个重定向类型,需要进行扩展。在switch
处理重定向指令的make_redirection
中有一个巨大的make_cmd.c
语句,实际的重定向由整个redir.c
中的函数执行。在其余的源代码中分散了各种用于打印,复制和销毁管道的功能,这些功能也可能需要更新。
这就是全部! Bash并不是 复杂。
这里没有讨论如何实现预先重定向,这很难,因为UNIX文件API只提供附加和覆盖。预先添加到文件的唯一方法是完全重写它,(正如其他答案所提到的)比任何现有的shell重定向要复杂得多。
答案 2 :(得分:1)
可能很难添加运算符,但是函数可能就足够了吗?
function prepend { tmp=`tempfile`; cp $1 $tmp; cat - $tmp > $1; rm $tmp; }
使用示例:
echo foobar | prepend file.txt
将文本“foobar”添加到file.txt。
答案 3 :(得分:0)
我认为bash的插件架构(通过'enable'内置命令加载共享对象)仅限于提供额外的内置命令。重定向运算符是运行简单命令的语法的一部分,因此我认为您需要修改解析器以识别和处理新的^>
运算符。
答案 4 :(得分:0)
大多数Linux文件系统不支持预先添加。事实上,我不知道任何一个拥有稳定用户空间接口的人。因此,正如其他人已经说过的那样,您只能依靠覆盖,只需要初始部分或整个文件,具体取决于您的需求。
您可以轻松(部分)覆盖Bash中的初始文件内容,而不会截断文件:
exec {fd}<>"$filename"
printf 'New initial contents' >$fd
exec {fd}>&-
上面,$fd
是Bash自动分配的文件描述符,$filename
是目标文件的名称。 Bash在第一行打开一个新的读写文件描述符到目标文件;这样做不截断文件。第二行会覆盖文件的初始部分。文件中的位置前进,因此您可以使用多个命令覆盖文件中的连续部分。第三行关闭描述符;由于每个进程只有有限的可用数量,因此您希望在不再需要它们之后关闭它们,或者长时间运行的脚本可能用完。
答案 5 :(得分:0)
请注意,>
的效果低于预期:
>
和以下单词,记住重定向。fork(2)
(或clone(2)
),以创建新流程。SOMEVAR=foo yourcommand
)等内容,还包括更改的文件描述符。此时,cmdline中的> yourfile
将使文件在stdout filedescriptor(即#1)处以只写模式截断时生成open(2)
文件为零字节。 >> yourfile
会导致文件在stdout中以只写模式和追加模式进行选择。execv(yourprogram, yourargs)
对于一个简单的例子,重定向可以像
一样实现open(yourfile, O_WRONLY|O_TRUNC);
或
open(yourfile, O_WRONLY|O_APPEND);
分别
然后启动的程序将设置正确的环境,并且可以愉快地写入fd1。从这里开始,不涉及shell 。真正的工作不是由shell完成的,而是由操作系统完成的。由于Unix没有前置模式(并且无法正确集成该功能),所以你可以尝试的一切都会陷入非常糟糕的黑客行为。
尝试重新考虑您的要求,总是更简单的方法。