我经常想做这样的事情:
cat file | command > file
(这显然不起作用)。我为此看到的唯一解决方案是sponge
,即
cat file | command | sponge file
不幸的是,sponge
它对我不可用(我也无法安装它或任何其他软件包)。
是否有一种更标准的快速方法来执行此操作,而不必每次都将其分解为多个命令(通过管道传输到临时文件,通过管道传输回原始文件,删除临时文件)?tee
例如,我尝试过,它似乎可以工作,但这是一个一致/安全的解决方案吗?
一个shell函数替换sponge
:
mysponge () (
append=false
while getopts 'a' opt; do
case $opt in
a) append=true ;;
*) echo error; exit 1
esac
done
shift "$(( OPTIND - 1 ))"
outfile=$1
tmpfile=$(mktemp "$(dirname "$outfile")/tmp-sponge.XXXXXXXX") &&
cat >"$tmpfile" &&
if "$append"; then
cat "$tmpfile" >>"$outfile"
else
if [ -f "$outfile" ]; then
chmod --reference="$outfile" "$tmpfile"
fi
if [ -f "$outfile" ]; then
mv "$tmpfile" "$outfile"
elif [ -n "$outfile" ] && [ ! -e "$outfile" ]; then
cat "$tmpfile" >"$outfile"
else
cat "$tmpfile"
fi
fi &&
rm -f "$tmpfile"
)
此mysponge
Shell函数将标准输入上可用的所有数据传递到一个临时文件中。
当所有数据都已重定向到临时文件后,收集的数据将被复制到该函数的参数命名的文件中。如果数据不附加到文件中(即-a
不使用),并且给定的输出文件名引用了现有的常规文件(如果不存在),则使用mv
(如果文件是现有的常规文件,则尝试chmod
先使用GNU将文件模式传输到临时文件)。如果输出的内容不是常规文件(命名管道,标准输出等),则使用来输出数据cat
。
如果在命令行上未提供文件,则收集的数据将发送到标准输出。
最后,将删除临时文件。
该功能中的每个步骤都取决于上一步的成功完成。如果一个命令失败(可能包含重要数据),则不会尝试删除该临时文件。
如果命名文件不存在,则将使用用户的默认权限等创建该文件,并将来自标准输入的数据写入其中。
该mktemp
实用程序不是标准的,但通常可用。
上述功能模拟物的行为中所描述的手册sponge
从moreutils
包在Debian。
用tee
代替sponge
并不是一个可行的选择。您说您已经尝试过了,它似乎很适合您。它可能会工作,可能不会。它取决于何时启动管道中的命令(它们几乎同时启动)的时间以及输入数据文件的大小。
以下是显示使用tee
不起作用的情况的示例。
原始文件为200000字节,但是在管道之后,它被截断为32 KiB(这很可能对应于我系统上的某些缓冲区大小)。
$ yes | head -n 100000 >hello
$ ls -l hello
-rw-r--r-- 1 kk wheel 200000 Jan 10 09:45 hello
$ cat hello | tee hello >/dev/null
$ ls -l hello
-rw-r--r-- 1 kk wheel 32768 Jan 10 09:46 hello
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句