Je viens de lancer le suivant dans Bash:
uniq .bash_history > .bash_history
et mon fichier d’histoire s’est retrouvé complètement vide.
Je suppose que j'ai besoin d'un moyen de lire le fichier en entier avant de l'écrire. Comment est-ce fait?
PS: J'ai évidemment pensé à utiliser un fichier temporaire, mais je cherche une solution plus élégante.
bash
ne mettra pas de dupes consécutives dans son historique si vous définissez HISTCONTROL pour inclure les ignoredups; voir la page de manuel.Réponses:
Je recommande d'utiliser
sponge
de moreutils . De la page de manuel:Pour appliquer cela à votre problème, essayez:
la source
Je voulais simplement apporter une autre réponse simple, qui n'utilise pas d'éponge (car souvent, elle n'est pas incluse dans les environnements légers).
devrait avoir le résultat souhaité. Le sous-shell est exécuté avant que .bash_history ne soit ouvert en é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 l'opérateur '>'.
la source
$()
au lieu de backticks en raison de problèmes qui échappaient.echo "$(fmt -p '# ' -w 50 readme.txt)" > readme.txt
aujourd'hui. Je cherchais depuis longtemps une solution élégante. Merci beaucoup, @Hart Simha!Le problème est que votre shell est en train de configurer 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 que l'uniq ne s'exécute. Cela va quelque chose comme:
>
fichier de sortie en écriture, le tronquantIl existe différentes solutions, y compris l'édition en place et l'utilisation de fichiers temporaires dont d'autres ont parlé, mais l'essentiel est de comprendre le problème, ce qui ne va vraiment pas et pourquoi.
la source
Une autre astuce pour ce faire, sans utiliser
sponge
, est la commande suivante:C'est l'une des astuces décrites dans l'excellent article « Éditer à la place» des fichiers sur backreference.org.
Fondamentalement, il ouvre le fichier en lecture, puis le "supprime". Ce n'est pas vraiment supprimé, cependant: 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 portant le même nom et y écrit les lignes uniques.
Inconvénient de cette solution: Si vous
uniq
échouez pour une raison quelconque, votre historique disparaîtra.la source
utiliser une éponge de moreutils
la source
Ce
sed
script supprime les doublons adjacents. Avec l'-i
option, la modification est effectuée sur place. C'est dused
info
fichier:la source
strace
illustration (pas que cela compte vraiment) :-)process input > tmp && mv tmp input
est beaucoup plus simple et lisible que d'utiliser lased
ruse simplement pour éviter un fichier temporaire et il ne remplacera pas mon fichier original s'il échoue (je ne sais pas si celased -i
échoue normalement). pense que ce serait bien). De plus, vous pouvez faire beaucoup de choses avec la méthode sortie-dans-fichier temporaire qui ne peut pas être faite sur place sans quelque chose d'encore plus complexe que cesed
script. Je sais que vous savez tout cela, mais certains spectateurs pourraient en bénéficier.Sed utilise également un fichier temporaire (ceci le fait pour vous):
Description: le fichier
temporaire
./sedPmPv9z
devient lefoo
fichier 4 et les fichiers le fichier 3. Les opérations de lecture se font sur le disque 3 et les écritures sur le disque 4 (le fichier temporaire). Le fichier foo est alors remplacé par le fichier temporaire de l'appel de changement de nom.la source
Une autre solution:
la source
Un fichier temporaire est à peu près tout, sauf si la commande en question prend en charge l’édition sur place (
uniq
ne le fait pas - certainssed
font (sed -i
)).la source
Vous pouvez utiliser Vim en mode Ex:
%
sélectionner toutes les lignes!
commande d'exécutionx
sauver et fermerla source
Vous pouvez également utiliser tee, en utilisant la sortie uniq comme entrée:
la source