Como foi mencionado, a esponja de moreutils é ótima. Eu uso esse script para emular para evitar a dependência do moreutils:
#!/bin/sh -e
#Soak up input and tee it to arguments
st=0; tmpf=
tmpf="'mktemp'" && exec 3<>"$tmpf" || st="$?"
rm -f "$tmpf" #remove it even if exec failed; noop if mktemp failed
[ "$st" = 0 ] || exit "$st"
cat >&3
</dev/fd/3 tee "$@" >/dev/null
Você pode usá-lo assim:
grep '^[a-zA-Z.:]' "$filepath" \
| sed -r '/^(rm|cd)/d' \
| uniq -u | sponge "$filepath"
Você não pode fazer isso com um simples redirecionamento de saída, porque os redirecionamentos ocorrem antes dos comandos serem iniciados e um redirecionamento de saída trunca o arquivo de saída.
Em outras palavras, quando o grep (o primeiro comando simples do pipeline) for iniciado, o último redirecionamento já truncou o arquivo de entrada / saída.
Não há realmente nenhum utilitário UNIX padrão que faça a verdadeira edição no local, até onde eu saiba. sed -i
apenas emula com um arquivo temporário. Eu acho que a razão é que a verdadeira filtragem inplace pode facilmente corromper o arquivo se uma etapa do pipeline falhar.
No que diz respeito ao que está acontecendo abaixo - ambos |
e <()
usam pipes do sistema que passam IO e um buffer de cada vez. O mecanismo não cria arquivos temporários (arquivos não-reais (sistema de arquivos)) e tenta evitar manter toda a entrada na memória de cada vez.