Datei nur überschreiben, wenn Daten

8

Ich versuche, eine Datei mit Befehlsausgabe zu überschreiben, aber nur, wenn eine Ausgabe vorhanden ist. Das heißt, ich möchte normalerweise

mycommand > myfile

aber wenn dies myfilemit leeren Daten überschrieben würde , möchte ich die alte Version von beibehalten myfile. Ich dachte, dass etwas mit ifnemöglich sein sollte, a la

mycommand | ifne (cat > myfile) 

aber das geht nicht ...

Ein indirekter Ansatz

mycommand | tee mytempfile | ifne mv mytempfile myfile

funktioniert, aber ich halte die Verwendung dieser temporären Datei für nicht relevant.

F: Warum funktioniert meine erste Idee nicht? Kann es funktionieren? Oder gibt es eine andere nette und vielleicht ganz andere Lösung für mein ursprüngliches Problem?

Hagen von Eitzen
quelle
5
"In eine separate Datei umleiten, die Größe dieser Datei überprüfen und möglicherweise umbenennen" scheint mir ziemlich einfach zu sein. Warum nicht eine temporäre Datei verwenden?
Jeff Schaller

Antworten:

18

Ihr erster Ansatz funktioniert, Sie müssen nur einen Befehl geben ifne(siehe 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.

Sie müssen ihm also einen Befehl zum Ausführen geben. Du bist fast da, teewird funktionieren:

command | ifne tee myfile > /dev/null

Wenn Ihr Befehl keine enorme Datenmenge erzeugt und klein genug ist, um in eine Variable zu passen, können Sie auch Folgendes tun:

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

Die Fußgängerlösung:

tmpfile=$(mktemp)

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

rm -f "$tmpfile"

Speichern Sie die Ausgabe in einer temporären Datei und testen Sie dann, ob sie leer ist oder nicht. Wenn es nicht leer ist, kopieren Sie den Inhalt über Ihre Datei. Löschen Sie am Ende die temporäre Datei.

Ich verwende cat "$tmpfile" >myfileeher als cp "$tmpfile" myfile(oder mv), um den gleichen Effekt zu erzielen, den Sie erhalten hätten mycommand >myfile, dh um die vorhandene Datei abzuschneiden und das Eigentum und die Berechtigungen beizubehalten.

Wenn sich $TMPDIR(verwendet von mktemp) auf einem speichermontierten Dateisystem befindet, wird dies nur beim Schreiben auf die Festplatte geschrieben myfile. Es wäre außerdem tragbarer als die Verwendung ifne.

Kusalananda
quelle