Sobrescribir archivo solo si los datos

8

Estoy tratando de sobrescribir un archivo con salida de comando, pero solo si hay alguna salida. Es decir, generalmente quiero

mycommand > myfile

pero si esto sobrescribiera myfilecon datos vacíos, deseo conservar la versión anterior de myfile. Pensé que algo usando ifnedebería ser posible, a la

mycommand | ifne (cat > myfile) 

Pero eso no funciona ...

Un enfoque indirecto

mycommand | tee mytempfile | ifne mv mytempfile myfile

funciona, pero considero que el uso de ese archivo temporal no es elegante.

P: ¿Por qué mi primera idea no funciona? ¿Se puede hacer funcionar? ¿O hay otra solución agradable y quizás completamente diferente para mi problema original?

Hagen von Eitzen
fuente
55
"Redirigir a un archivo separado, verificar el tamaño de ese archivo y posiblemente renombrarlo" me parece bastante sencillo. ¿Por qué no usar un archivo temporal?
Jeff Schaller

Respuestas:

18

Su primer enfoque funciona, solo necesita dar un comando para ifne(ver 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.

Por lo tanto, debe darle un comando para que se ejecute. Ya casi estás allí, teefuncionará:

command | ifne tee myfile > /dev/null

Si su comando no produce una gran cantidad de datos, si es lo suficientemente pequeño como para caber en una variable, también puede hacer:

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

La solución peatonal:

tmpfile=$(mktemp)

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

rm -f "$tmpfile"

Es decir, guarde el resultado en un archivo temporal, luego pruebe si está vacío o no. Si no está vacío, copie su contenido sobre su archivo. Al final, elimine el archivo temporal.

Estoy usando en cat "$tmpfile" >myfilelugar de cp "$tmpfile" myfile(o mv) para obtener el mismo efecto que habría obtenido mycommand >myfile, es decir, para truncar el archivo existente y preservar la propiedad y los permisos.

Si $TMPDIR(utilizado por mktemp) está en un sistema de archivos montado en memoria, entonces esto no escribiría en el disco de otra manera que no sea cuando se escribe en myfile. Además, sería más portátil que usar ifne.

Kusalananda
fuente