Shell - Ecrire le contenu des variables dans un fichier

95

Je voudrais copier le contenu d'une variable (appelée ici var) dans un fichier.

Le nom du fichier est stocké dans une autre variable destfile.

J'ai des problèmes à faire ça. Voici ce que j'ai essayé:

cp $var $destfile

J'ai aussi essayé la même chose avec la commande dd ... De toute évidence, le shell a pensé que cela $varfaisait référence à un répertoire et m'a donc dit que le répertoire était introuvable.

Comment puis-je contourner cela?

user1546083
la source
2
Veuillez améliorer votre question en publiant un code correctement formaté qui montre comment vous remplissez vos variables et tous les messages d'erreur pertinents exactement tels qu'ils apparaissent.
Todd A. Jacobs
2
Qu'entendez-vous par "copier le contenu d'une variable" dans un répertoire? $varSpécifie- t-il un nom de fichier ou du texte à écrire dans un fichier? S'il spécifie du texte, quel est le nom du fichier dans lequel vous souhaitez écrire ce contenu?
jahroy
$ var contient le texte que je souhaite copier et le fichier dans lequel il doit être écrit est défini par l'utilisateur, d'où la raison pour laquelle j'utilise une variable en premier lieu.
user1546083
1
Peut $destdir-être devrait être nommé $destfilepour que ce ne soit pas trompeur ... Le nom $destdirsuggère qu'il spécifie un répertoire plutôt qu'un fichier. Cela rendrait toute votre question simple et facile à comprendre.
jahroy

Réponses:

145

Utilisez la echocommande:

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

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

Les iftests qui $destdirreprésentent un fichier.

Le >ajoute le texte après avoir tronqué le fichier. Si vous souhaitez uniquement ajouter le texte au $varcontenu existant du fichier, utilisez à la >>place:

echo "$var" >> "$destdir"

le cp commande est utilisée pour copier des fichiers (dans des fichiers), pas pour écrire du texte dans un fichier.

pb2q
la source
4
Besoin de plus de guillemets - pour le moment, toutes les exécutions d'espaces dans la valeur de la variable seront converties en un seul espace, les expressions glob seront développées, etc.
Charles Duffy
2
Une autre chose - vous avez besoin d'un espace entre le devis de clôture et le ]in "$destdir"].
Charles Duffy
3
echoajoute également une nouvelle ligne de fin à votre variable.
Ben Dilts
6
Cela échoue si $varc'est le cas -e text to appendet n'écrit pas réellement le-e
Eric
1
Parce que echo $vars'appuyer sur le shell pour développer votre variable, cela ne fonctionne pas très bien avec des choses comme les espaces blancs et les caractères spéciaux. Vous pouvez utiliser à la perl -e 'print($ENV{var})'place, et il affichera précisément la valeur de la variable.
Blake Mitchell
38

echoa le problème que si varcontient quelque chose comme -e, il sera interprété comme un drapeau. Une autre option est printf, mais printf "$var" > "$destdir"développera tous les caractères d'échappement dans la variable, donc si la variable contient des barres obliques inverses, le contenu du fichier ne correspondra pas. Cependant, comme printfn'interprète que les contre-obliques comme des échappements dans la chaîne de format, vous pouvez utiliser le %sspécificateur de format pour stocker le contenu exact de la variable dans le fichier de destination:

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

Trebawa
la source
1
printf est également bon si vous avez des retours à la ligne dans la chaîne variable, comme à partir d'un triple quote ou heredoc. echo ne gère pas bien les nouvelles lignes.
beeflobill
@beeflobill pouvez-vous expliquer comment "echo ne gère pas bien les nouvelles lignes". La seule chose que j'ai vue, c'est que l'écho ajoute une nouvelle ligne. Ce qui fait echo "$var" > destfilemal.
SensorSmith
@SensorSmith Dans mes expériences, je vois que lorsque la chaîne a "\ n" cet écho affichera un caractère de nouvelle ligne. Mais, si la chaîne a un caractère de nouvelle ligne, l'écho ne l'imprimera pas. Je ne sais pas pourquoi.
beeflobill
1
Fondamentalement, un problème de portabilité (et de fiabilité). unix.stackexchange.com/a/65819… ou pour les mortels d'entre nous: printfc'est mieux, passez à autre chose.
user3342816
29

Aucune des réponses ci-dessus ne fonctionne si votre variable:

  • commence avec -e
  • commence avec -n
  • commence avec -E
  • contient un \suivi d'unn
  • ne devrait pas avoir une nouvelle ligne supplémentaire ajoutée après

et ainsi ils ne peuvent pas être invoqués pour le contenu de chaîne arbitraire.

Dans bash, vous pouvez utiliser "here strings" comme:

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

Comme indiqué dans le commentaire ci-dessous, l' utilisation de la réponse de @ Trebawa (formulée dans la même pièce que la mienne!) printfEst une meilleure approche.

Eric
la source
5
D'après ce que je peux dire, cat insérera toujours une nouvelle ligne à la fin du fichier, même s'il n'y a pas de nouvelle ligne à la fin de la variable (bien que ce soit sans doute une bonne chose dans la plupart des cas). La réponse utilisant printf semble éviter d'insérer une nouvelle ligne de fin.
Ash
@Ash un autre avantage de printfover catest que le premier est un shell intégré qui s'exécutera toujours plus rapidement qu'un binaire externe.
Géza Török le
7

Si je vous ai bien compris, vous souhaitez copier $vardans un fichier (si c'est une chaîne).

echo $var > $destdir
qwertz
la source
C'est comme ça que ça se fait. L'utilisation de la cpcommande obligera le shell à interpréter le premier argument comme le nom d'un fichier ou d'un répertoire.
jahroy
5
Si vous n'insérez pas de $varguillemets, le contenu du fichier n'est pas à 100% égal au contenu de $ var dans certains cas. Par exemple, lorsque vous "faites écho" des variables contenant des clés RSA, vous obtenez une clé non valide dans le fichier.
srigi
6
Échoue si $varcontient des espaces ou-e
Eric
1

Lorsque vous dites «copier le contenu d'une variable», cette variable contient-elle un nom de fichier ou contient-elle le nom d'un fichier?

Je suppose par votre question que $varcontient le contenu que vous souhaitez copier dans le fichier:

$ echo "$var" > "$destdir"

Cela fera écho à la valeur de $ var dans un fichier appelé $ destdir. Notez les citations. Très important d'avoir "$ var" entre guillemets. Aussi pour "$ destdir" s'il y a un espace dans le nom. Pour l'ajouter:

$ echo "$var" >> "$destdir"
David W.
la source
3
Échec si varcontient-e
Eric
1
Passer un double trait d'union comme premier argument pour echo terminer sa liste d'options, résout ainsi le problème soulevé par @Eric:echo -- "$var" >> "$destfile"
Géza Török le
1

Tout ce qui précède fonctionne, mais doit également contourner un problème (échappements et caractères spéciaux) qui n'a pas besoin de se produire en premier lieu: les caractères spéciaux lorsque la variable est développée par le shell. Ne faites pas cela (expansion variable) en premier lieu. Utilisez la variable directement, sans développement.

De plus, si votre variable contient un secret et que vous souhaitez copier ce secret dans un fichier, vous voudrez peut-être ne pas avoir d'extension dans la ligne de commande car le traçage / écho de commande des commandes shell pourrait révéler le secret. Signifie, toutes les réponses qui utilisent$var dans la ligne de commande peuvent présenter un risque de sécurité potentiel en exposant le contenu de la variable au traçage et à la journalisation du shell.

Utilisez ceci:

printenv var >file

Cela signifie, en cas de question OP:

printenv var >"$destfile"
Christian Hujer
la source