J'ai un fichier temp.txt, que je veux trier avec la sort
commande en bash.
Je veux que les résultats triés remplacent le fichier d'origine.
Cela ne fonctionne pas par exemple (j'obtiens un fichier vide):
sortx temp.txt > temp.txt
Cela peut-il être fait en une seule ligne sans recourir à la copie dans des fichiers temporaires?
EDIT: L' -o
option est très cool pour sort
. J'ai utilisé sort
dans ma question comme exemple. Je rencontre le même problème avec d'autres commandes:
uniq temp.txt > temp.txt.
Existe-t-il une meilleure solution générale?
Réponses:
la source
sort --inplace *.txt
? Ce serait cool foufind . -name \*.txt -exec sort {} -o {} \;
Un a
sort
besoin de voir toutes les entrées avant de pouvoir commencer à sortir. Pour cette raison, lesort
programme peut facilement offrir une option pour modifier un fichier sur place:Plus précisément, la documentation de GNU
sort
dit:Alors que la documentation de BSD
sort
dit:Les commandes telles que
uniq
peuvent commencer à écrire la sortie avant de terminer la lecture de l'entrée. Ces commandes ne prennent généralement pas en charge l'édition sur place (et il leur serait plus difficile de prendre en charge cette fonctionnalité).Vous travaillez généralement autour de cela avec un fichier temporaire, ou si vous voulez absolument éviter d'avoir un fichier intermédiaire, vous pouvez utiliser un tampon pour stocker le résultat complet avant de l'écrire. Par exemple, avec
perl
:Ici, la partie perl lit la sortie complète de
uniq
in variable$_
puis écrase le fichier d'origine avec ces données. Vous pouvez faire de même dans le langage de script de votre choix, peut-être même dans Bash. Mais notez qu'il aura besoin de suffisamment de mémoire pour stocker le fichier entier, ce n'est pas conseillé lorsque vous travaillez avec des fichiers volumineux.la source
Voici une approche plus générale, fonctionne avec uniq, sort et autres.
la source
sponge
des moreutils:cat file |frobnicate |sponge file
.Le commentaire de Tobu sur l'éponge justifie d'être une réponse à part entière.
Pour citer la page d'accueil de moreutils :
Cependant,
sponge
souffre du même problème que Steve Jessop commente ici. Si l'une des commandes du pipeline avantsponge
échoue, le fichier d'origine sera écrasé.Oh-oh,
my-important-file
est parti.la source
set -o pipefail
au début de votre script, l'erreur surmistyped_command my-important-file
ferait la sortie du script immédiatement, avant de s'exécutersponge
, préservant ainsi le fichier important.Voilà, une ligne:
Techniquement, il n'y a pas de copie dans un fichier temporaire et la commande «mv» devrait être instantanée.
la source
J'aime le
sort file -o file
réponse mais je ne veux pas taper deux fois le même nom de fichier.Utilisation de l'expansion de l'historique BASH :
saisit le premier argument de la ligne actuelle lorsque vous appuyez sur enter .
Un tri unique en place:
attrape le dernier argument de la ligne courante.
la source
Beaucoup ont mentionné le -o option . Voici la partie de la page de manuel.
Depuis la page de manuel:
la source
Ce serait très contraint en mémoire, mais vous pouvez utiliser awk pour stocker les données intermédiaires en mémoire, puis les réécrire.
la source
>
le fichier tronque le fichier avant que la commande (uniq
dans ce cas) ne le lise.Une alternative aux
sponge
plus courantssed
:Il fonctionne pour toute commande (
sort
,uniq
,tac
, ...) et utilise le très bien connused
d »-i
options (fichiers modifier en place).Avertissement: essayez d'
command file
abord, car la modification des fichiers sur place n'est pas sûre par nature.Explication
Tout d' abord, vous dire de
sed
ne pas imprimer les lignes ( d' origine) ( l'-n
option ), et avec l'aide de lased
« sr
commande etbash
» s Remplacement du processus , le contenu généré par<(command file)
sera la sortie enregistrée en place .Rendre les choses encore plus faciles
Vous pouvez envelopper cette solution dans une fonction:
Exemple
la source
Utilisez l'argument
--output=
ou-o
Je viens d'essayer sur FreeBSD:
la source
Pour ajouter la
uniq
capacité, quels sont les inconvénients à:la source
Lire sur l'éditeur non interactif,
ex
.la source
Si vous insistez pour utiliser le
sort
programme, vous devez utiliser un fichier intermédiaire - je ne pense pas qu'il ysort
ait d'option de tri en mémoire. Toute autre astuce avec stdin / stdout échouera à moins que vous ne puissiez garantir que la taille de la mémoire tampon pour stdin de sort est suffisamment grande pour contenir le fichier entier.Edit: honte à moi.
sort temp.txt -o temp.txt
fonctionne très bien.la source
Une autre solution:
la source
<>
astuce ne fonctionne que dans ce cas car elleuniq
est spéciale en ce qu'elle ne copie que les lignes d'entrée sur les lignes de sortie, en laissant tomber certaines en cours de route. Si une autre commande (par exemplesed
) a été utilisée qui changerait l'entrée (par exemple changerait touta
enaa
), alors elle peut remplacerfile
d'une manière qui n'a aucun sens et même boucler à l'infini, à condition que l'entrée soit suffisamment grande (plus qu'un tampon de lecture unique).