Solution 1 :
echo "$(uniq .bash_history)" > .bash_history
devrait avoir le résultat souhaité. Le sous-shell est exécuté avant .bash_history
est ouvert à l'écriture. Comme expliqué dans la réponse de Phil P, au moment où .bash_history
est lu dans la commande d'origine, il a déjà été tronqué par le >
opérateur.
Solution 2 :
Je recommande d'utiliser sponge
de moreutils. À partir de la page de manuel :
DESCRIPTION
sponge reads standard input and writes it out to the specified file. Unlike
a shell redirect, sponge soaks up all its input before opening the output file.
This allows for constructing pipelines that read from and write to the same
file.
Pour appliquer cela à votre problème, essayez :
uniq .bash_history | sponge .bash_history
Solution 3 :
Le problème est que votre shell configure le pipeline de commandes avant d'exécuter les commandes. Ce n'est pas une question "d'entrée et de sortie", c'est que le contenu du fichier est déjà parti avant même qu'uniq ne s'exécute. Ça donne quelque chose comme :
- Le shell ouvre le
>
fichier de sortie pour l'écriture, en le tronquant - Le shell est configuré pour que le descripteur de fichier 1 (pour stdout) soit utilisé pour cette sortie
- Le shell exécute uniq, peut-être quelque chose comme execlp("uniq", "uniq", ".bash_history", NULL)
- uniq s'exécute, ouvre .bash_history et n'y trouve rien
Il existe différentes solutions, y compris l'édition sur place et l'utilisation de fichiers temporaires que d'autres mentionnent, mais la clé est de comprendre le problème, ce qui ne va pas et pourquoi.
Solution 4 :
Une autre astuce pour faire cela, sans utiliser sponge
, est la commande suivante :
{ rm .bash_history && uniq > .bash_history; } < .bash_history
C'est l'une des astuces décrites dans l'excellent article Modification "sur place" des fichiers sur backreference.org.
Il ouvre essentiellement le fichier en lecture, puis le "supprime". Cependant, il n'est pas vraiment supprimé :il y a un descripteur de fichier ouvert pointant vers lui, et tant qu'il reste ouvert, le fichier est toujours là. Ensuite, il crée un nouveau fichier avec le même nom et y écrit les lignes uniques.
Inconvénient de cette solution :Si uniq
échoue pour une raison quelconque, votre historique disparaîtra.
Solution 5 :
utiliser une éponge de moreutils
uniq .bash_history | sponge .bash_history