Sobrescrever arquivo somente se os dados

8

Estou tentando substituir um arquivo com saída de comando, mas apenas se houver alguma saída. Ou seja, eu normalmente quero

mycommand > myfile

mas se isso sobrescrever myfilecom dados vazios, desejo manter a versão antiga do myfile. Eu pensei que algo usando ifnedeveria ser possível, a la

mycommand | ifne (cat > myfile) 

mas isso não funciona ...

Uma abordagem indireta

mycommand | tee mytempfile | ifne mv mytempfile myfile

funciona, mas considero deselegante o uso desse arquivo temporário.

P: Por que minha primeira ideia não funciona? Isso pode ser feito? Ou existe outra solução agradável e talvez completamente diferente para o meu problema original?

Hagen von Eitzen
fonte
5
"Redirecionar para um arquivo separado, verificar o tamanho desse arquivo e possivelmente renomeá-lo" parece bastante direto para mim. Por que não usar um arquivo temporário?
Jeff Schaller

Respostas:

18

Sua primeira abordagem funciona, você só precisa dar um comando para ifne(consulte man ifne):

NAME
       ifne - Run command if the standard input is not empty

SYNOPSIS
       ifne [-n] command

DESCRIPTION
       ifne  runs  the  following command if and only if the standard input is
       not empty.

Então você precisa dar um comando para executar. Você está quase lá, teevai funcionar:

command | ifne tee myfile > /dev/null

Se o seu comando não produzir uma quantidade enorme de dados, se for pequeno o suficiente para caber em uma variável, você também poderá:

var=$(mycommand)
[[ -n $var ]] && printf '%s\n' "$var" > myfile
terdon
fonte
8

A solução para pedestres:

tmpfile=$(mktemp)

mycommand >"$tmpfile"
if [ -s "$tmpfile" ]; then
    cat "$tmpfile" >myfile
fi

rm -f "$tmpfile"

Ou seja, salve a saída em um arquivo temporário e teste se está vazio ou não. Se não estiver vazio, copie o conteúdo do seu arquivo. No final, exclua o arquivo temporário.

Estou usando, em cat "$tmpfile" >myfilevez de cp "$tmpfile" myfile(ou mv), para obter o mesmo efeito que você obteria mycommand >myfile, ou seja, truncar o arquivo existente e preservar a propriedade e as permissões.

Se $TMPDIR(usado por mktemp) estiver em um sistema de arquivos montado na memória, isso não gravará no disco, exceto possivelmente ao gravar no myfile. Além disso, seria mais portátil do que usar ifne.

Kusalananda
fonte