Avertissement concernant '>'
Les débutants Unix qui viennent d’apprendre la redirection des E / S ( <
et >
) essaient souvent des choses comme:
commande ... fichier_entrée > the_same_file
ou
commande … < fichier > the_same_file
ou, presque équivalent,
dossier de chat | commande …> the_same_file
( grep
, sed
, cut
, sort
Et spell
sont des exemples de commandes que les gens sont tentés d'utiliser dans les constructions comme celles - ci.) Les utilisateurs sont surpris de découvrir que ces scénarios aboutissent dans le fichier se vider.
Une nuance qui ne semble pas être mentionnée dans l'autre réponse se cache dans la première phrase de la section Redirection de bash (1) :
Avant qu'une commande ne soit exécutée, son entrée et sa sortie peuvent être redirigées à l'
aide d'une notation spéciale interprétée par le shell.
Les cinq premiers mots doivent être en gras, en italique, souligné, agrandi, clignotant, coloré en rouge et marqué d'une icône pour souligner le fait que le shell effectue la ou les redirection (s) demandée (s)
avant l'exécution de la commande . Et rappelez-vous aussi
La redirection de la sortie entraîne l’ouverture du fichier… en écriture…. Si le fichier n'existe pas, il est créé. s'il existe, il est tronqué à une taille nulle.
Donc, dans cet exemple:
sort roster > roster
le shell ouvre le roster
fichier en écriture en le tronquant (c.-à-d. en supprimant tout son contenu) avant que le sort
programme ne commence à s'exécuter. Naturellement, rien ne peut être fait pour récupérer les données.
On pourrait s'attendre naïvement à ce que
tr "[:upper:]" "[:lower:]" < poem > poem
pourrait être mieux. Comme le shell gère les redirections de gauche à droite, il s'ouvre poem
en lecture (pour tr
l'entrée standard de), avant de l'écrire en écriture (pour la sortie standard). Mais ça n'aide pas. Même si cette séquence d'opérations génère deux descripteurs de fichier, ils renvoient tous deux au même fichier. Lorsque le shell ouvre le fichier en lecture, le contenu est toujours là, mais il continue à être compressé avant l'exécution du programme.
Alors, que faire à ce sujet?
Les solutions comprennent:
Vérifiez si le programme que vous exécutez dispose de sa propre capacité interne permettant de spécifier l'emplacement de la sortie. Ceci est souvent indiqué par un -o
(ou --output=
) jeton. En particulier,
sort roster -o roster
est à peu près équivalent à
sort roster > roster
sauf que, dans le premier cas, le sort
programme ouvre le fichier de sortie. Et il est assez intelligent pour ne pas ouvrir le fichier de sortie jusqu'à ce que après avoir lu tous les fichiers d'entrée (s).
De même, au moins certaines versions de sed
ont une option -i
(edit i n place) qui peut être utilisée pour écrire la sortie dans le fichier d’entrée (à nouveau, après que toutes les entrées aient été lues). Éditeurs comme ed
/ ex
, emacs
, pico
et vi
/ vim
permettent à l'utilisateur d'éditer un fichier texte et enregistrez le texte modifié dans le fichier d' origine. Notez que ed
(au moins) peut être utilisé de manière non interactive.
vi
a une caractéristique connexe. Si vous tapez , le contenu du tampon d'édition sera écrit , la sortie et insérée dans le tampon (en remplacement du contenu d'origine).:%!command
Entercommand
Simple mais efficace:
commande ... fichier_entrée > TEMP_FILE && mv TEMP_FILE fichier_entrée
Cela a pour inconvénient que, s’il input_file
s’agit d’un lien, il sera (probablement) remplacé par un fichier séparé. En outre, le nouveau fichier appartiendra à vous, avec les protections par défaut. Cela risque en particulier de rendre le fichier lisible par tout le monde, même si le fichier original input_file
ne l’était pas.
Variations:
command … input_file > temp_file && cp temp_file input_file && rm temp_file
qui laissera (potentiellement) le temp_file
monde lisible. Encore mieux:
cp input_file temp_file && command … temp_file > input_file && rm temp_file
Celles-ci préservent l’état de la liaison, le propriétaire et le mode (protection) du fichier, éventuellement au prix de deux fois plus d’E / S. (Vous devrez peut - être utiliser une option comme -a
ou -p
sur cp
pour lui dire de conserver les attributs.)
command … input_file > temp_file &&
cp --attributes-only --preserve=all input_file temp_file &&
mv temp_file input_file
(divisé en lignes séparées uniquement pour des raisons de lisibilité) Cela préserve le mode du fichier (et, si vous êtes root, le propriétaire), mais le fait appartenir à vous (si vous n'êtes pas root), et en fait un nouveau, fichier séparé.
Ce blog
(édition de fichiers «sur place») suggère et explique
{rm input_file && command …> input_file ; } < fichier_entrée
Cela nécessite de command
pouvoir traiter les entrées standard (mais presque tous les filtres le peuvent). Le blog lui-même appelle cela un kludge risqué et décourage son utilisation. Et cela créera également un nouveau fichier séparé (non lié à quoi que ce soit), appartenant à vous et avec les autorisations par défaut.
Le paquet moreutils a une commande appelée sponge
:
commande … fichier_entrée | éponge le_same_file
Voir cette réponse pour plus d'informations.
Voici quelque chose qui m'a complètement surprise:
syntaxerror dit :
[La plupart de ces solutions] échouera sur un système de fichiers en lecture seule, où «lecture seule» signifie que vous $HOME
serez en écriture, mais /tmp
en lecture seule (par défaut). Par exemple, si vous avez Ubuntu et que vous avez démarré dans la console de récupération, c'est généralement le cas. En outre, l'opérateur here-document <<<
n'y travaillera pas non plus, car il doit /tmp
être lu / écrit
car il y écrit également un fichier temporaire.
(cf. cette question inclut une strace
sortie 'd)
Ce qui suit peut fonctionner dans ce cas:
Alors, quelle était la question?
Cela a été un sujet populaire sur U & L; il est abordé dans les questions suivantes:
… Et cela ne compte pas Super User ou Ask Ubuntu. J'ai incorporé beaucoup d'informations des réponses aux questions ci-dessus dans cette réponse, mais pas toutes. (Par exemple, pour plus d'informations, lisez les questions ci-dessus et leurs réponses.)
PS Je n'ai aucune affiliation avec le blog que j'ai cité ci-dessus.