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.
bashne 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
spongede 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.txtaujourd'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 tronquant
Il 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
sedscript supprime les doublons adjacents. Avec l'
-ioption, la modification est effectuée sur place. C'est du
sed
infofichier:
la source
straceillustration (pas que cela compte vraiment) :-)
process input > tmp && mv tmp inputest beaucoup plus simple et lisible que d'utiliser la
sedruse simplement pour éviter un fichier temporaire et il ne remplacera pas mon fichier original s'il échoue (je ne sais pas si cela
sed -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 ce
sedscript. 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
./sedPmPv9zdevient le
foofichier 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 (
uniqne le fait pas - certains
sedfont (
sed -i)).
la source
Vous pouvez utiliser Vim en mode Ex:
%sélectionner toutes les lignes
!commande d'exécution
xsauver et fermer
la source
Vous pouvez également utiliser tee, en utilisant la sortie uniq comme entrée:
la source