Shell - Schreiben Sie variablen Inhalt in eine Datei

92

Ich möchte den Inhalt einer Variablen (hier aufgerufen var) in eine Datei kopieren .

Der Name der Datei wird in einer anderen Variablen gespeichert destfile.

Ich habe Probleme damit. Folgendes habe ich versucht:

cp $var $destfile

Ich habe das gleiche auch mit dem Befehl dd versucht ... Offensichtlich dachte die Shell, dass sie $varsich auf ein Verzeichnis bezieht, und sagte mir, dass das Verzeichnis nicht gefunden werden konnte.

Wie komme ich darum herum?

user1546083
quelle
2
Bitte verbessern Sie Ihre Frage, indem Sie einen ordnungsgemäß formatierten Code veröffentlichen, der zeigt, wie Sie Ihre Variablen füllen, und alle relevanten Fehlermeldungen genau so, wie sie angezeigt werden.
Todd A. Jacobs
2
Was meinst du mit "Kopieren des Inhalts einer Variablen" in ein Verzeichnis? Gibt $vareinen Dateinamen oder einen Text an, der in eine Datei geschrieben werden soll? Wenn Text angegeben wird, wie lautet dann der Name der Datei, in die Sie diesen Inhalt schreiben möchten?
Jahroy
$ var enthält den Text, den ich kopieren möchte, und die Datei, in die er geschrieben werden soll, ist benutzerdefiniert, daher verwende ich überhaupt eine Variable.
user1546083
1
Vielleicht $destdirsollte es benannt werden, $destfiledamit es nicht irreführend ist ... Der Name $destdirlegt nahe, dass es eher ein Verzeichnis als eine Datei angibt. Dies würde Ihre ganze Frage einfach und leicht verständlich machen.
Jahroy

Antworten:

142

Verwenden Sie den echoBefehl:

var="text to append";
destdir=/some/directory/path/filename

if [ -f "$destdir" ]
then 
    echo "$var" > "$destdir"
fi

Die ifTests, $destdirdie eine Datei darstellen.

Der >Text wird nach dem Abschneiden der Datei angehängt. Wenn Sie den Text nur $varan den vorhandenen Inhalt der Datei anhängen möchten , verwenden Sie >>stattdessen:

echo "$var" >> "$destdir"

Der cpBefehl wird zum Kopieren von Dateien (in Dateien) verwendet, nicht zum Schreiben von Text in eine Datei.

pb2q
quelle
4
Benötigt mehr Anführungszeichen - im Moment werden alle Leerzeichen innerhalb des Variablenwerts in ein einzelnes Leerzeichen konvertiert, Glob-Ausdrücke werden erweitert usw.
Charles Duffy
2
Eine andere Sache - Sie benötigen ein Leerzeichen zwischen dem Schlusszitat und dem ]In "$destdir"].
Charles Duffy
3
echoFügt Ihrer Variablen auch einen nachgestellten Zeilenumbruch hinzu.
Ben Dilts
6
Dies schlägt fehl, wenn es $varist -e text to append, und schreibt nicht wirklich-e
Eric
1
Da Sie echo $varsich beim Erweitern Ihrer Variablen auf die Shell verlassen, funktioniert dies mit Leerzeichen und Sonderzeichen nicht sehr gut. Sie können perl -e 'print($ENV{var})'stattdessen verwenden, und es wird genau der Wert der Variablen ausgegeben.
Blake Mitchell
37

echohat das Problem, dass wenn es so varetwas enthält -e, es als Flag interpretiert wird. Eine andere Option ist printf, printf "$var" > "$destdir"erweitert jedoch alle maskierten Zeichen in der Variablen. Wenn die Variable also Backslashes enthält, stimmt der Dateiinhalt nicht überein. Da printfBackslashes jedoch nur als Escapezeichen in der Formatzeichenfolge interpretiert werden, können Sie den %sFormatbezeichner verwenden, um den genauen Variableninhalt in der Zieldatei zu speichern:

printf "%s" "$var" > "$destdir"

Trebawa
quelle
1
printf ist auch gut, wenn Sie Zeilenumbrüche in der variablen Zeichenfolge haben, z. B. aus einem dreifachen Anführungszeichen oder einem Heredoc. Echo kann mit den Zeilenumbrüchen nicht gut umgehen.
Beeflobill
@beeflobill können Sie erklären, wie "Echo die Zeilenumbrüche nicht gut handhabt". Das einzige, was ich gesehen habe, ist, dass Echo eine neue Zeile hinzufügt. Was echo "$var" > destfilefalsch macht.
SensorSmith
@SensorSmith In meinen Experimenten sehe ich, dass dieses Echo ein Zeilenumbruchzeichen druckt, wenn die Zeichenfolge "\ n" hat. Wenn die Zeichenfolge jedoch ein tatsächliches Zeilenumbruchzeichen enthält, wird sie vom Echo nicht gedruckt. Ich weiß nicht warum.
Beeflobill
1
Grundsätzlich ein Problem der Portabilität (und Zuverlässigkeit). unix.stackexchange.com/a/65819… oder für die Tödlichen unter uns: printfist besser, mach weiter.
user3342816
29

Keine der obigen Antworten funktioniert, wenn Ihre Variable:

  • beginnt mit -e
  • beginnt mit -n
  • beginnt mit -E
  • enthält ein \gefolgt von einemn
  • sollte keine zusätzliche Newline danach angehängt werden

Daher können sie nicht für beliebige Zeichenfolgeninhalte verwendet werden.

In Bash können Sie "Here Strings" verwenden als:

cat <<< "$var" > "$destdir"

Wie im Kommentar unten erwähnt, ist die Antwort von @ Trebawa (formuliert im selben Raum wie meine!) printfEin besserer Ansatz.

Eric
quelle
5
Nach allem, was ich sagen kann, fügt cat immer eine neue Zeile am Ende der Datei ein, unabhängig davon, ob am Ende der Variablen keine neue Zeile steht (obwohl dies in den meisten Fällen wohl eine gute Sache ist). Die Antwort mit printf scheint das Einfügen einer nachgestellten Newline zu vermeiden.
Ash
@Ash Ein weiterer Vorteil von printfover catist, dass Ersteres eine eingebaute Shell ist, die immer schneller ausgeführt wird als eine externe Binärdatei.
Géza Török
7

Wenn ich Sie richtig verstanden habe, möchten Sie $varin eine Datei kopieren (wenn es sich um eine Zeichenfolge handelt).

echo $var > $destdir
qwertz
quelle
So wird es gemacht. Mit dem cpBefehl interpretiert die Shell das erste Argument als Namen einer Datei oder eines Verzeichnisses.
Jahroy
5
Wenn Sie keine $varAnführungszeichen einfügen, entspricht der Inhalt der Datei in einigen Fällen nicht zu 100% dem Inhalt von $ var. Wenn Sie beispielsweise Variablen "wiedergeben", die RSA-Schlüssel enthalten, erhalten Sie einen ungültigen Schlüssel in der Datei.
Srigi
6
Schlägt fehl, wenn $varLeerzeichen enthalten sind oder-e
Eric
1

Wenn Sie "Inhalt einer Variablen kopieren" sagen, enthält diese Variable einen Dateinamen oder einen Dateinamen?

Ich gehe von Ihrer Frage aus, $vardie den Inhalt enthält, den Sie in die Datei kopieren möchten:

$ echo "$var" > "$destdir"

Dadurch wird der Wert von $ var in eine Datei mit dem Namen $ destdir übertragen. Beachten Sie die Anführungszeichen. Sehr wichtig, dass "$ var" in Anführungszeichen steht. Auch für "$ destdir", wenn der Name ein Leerzeichen enthält. Um es anzuhängen:

$ echo "$var" >> "$destdir"
David W.
quelle
3
Schlägt fehl, wenn varenthält-e
Eric
1
Das Übergeben eines doppelten Bindestrichs als erstes Argument zum echo Beenden der Optionsliste löst somit das von @Eric aufgeworfene Problem:echo -- "$var" >> "$destfile"
Géza Török
0

Alle oben genannten Funktionen funktionieren, müssen jedoch auch ein Problem (Escapezeichen und Sonderzeichen) umgehen, das überhaupt nicht auftreten muss: Sonderzeichen, wenn die Variable durch die Shell erweitert wird. Tun Sie das einfach nicht (variable Erweiterung). Verwenden Sie die Variable direkt ohne Erweiterung.

Wenn Ihre Variable ein Geheimnis enthält und Sie dieses Geheimnis in eine Datei kopieren möchten, möchten Sie möglicherweise keine Erweiterung in der Befehlszeile, da die Ablaufverfolgung / das Befehlsecho der Shell-Befehle das Geheimnis möglicherweise enthüllt. Das heißt, alle Antworten, die $varin der Befehlszeile verwendet werden, können ein potenzielles Sicherheitsrisiko darstellen, indem der Inhalt der Variablen der Verfolgung und Protokollierung der Shell ausgesetzt wird.

Benutze das:

printenv var >file

Das heißt, im Fall der OP-Frage:

printenv var >"$destfile"
Christian Hujer
quelle