Suis-je aveugle ou n'y a-t-il pas d'option comme --in-place
pour sort
?
Pour enregistrer les résultats dans le fichier d'entrée, sed utilise -i
(--in-place
).
Rediriger la sortie de sort
vers le fichier d'entrée
sort < f > f
résulte en le rendant vide. Si il n'y a pas --in-place
option - il y a peut-être une astuce pour le faire de la manière pratique?
(La seule chose qui me vient à l'esprit:
sort < f > /tmp/f$$ ; cat /tmp/f$$ > f ; rm /tmp/f$$
Le déplacement n'est pas le bon choix, car autorisations de fichier peut être modifié. C'est pourquoi j'écrase le contenu du fichier temporaire que je supprime ensuite.)
sort
a le -o, --output
option qui prend un nom de fichier comme argument. S'il est identique au fichier d'entrée, il écrit le résultat dans un fichier temporaire, puis écrase le fichier d'entrée d'origine (exactement la même chose que ce que sed -i
Est-ce que).
De GNU sort
page d'informations:
`-o OUTPUT-FILE'
`--output=OUTPUT-FILE'
Write output to OUTPUT-FILE instead of standard output. Normally,
`sort' reads all input before opening OUTPUT-FILE, so you can
safely sort a file in place by using commands like `sort -o F F'
and `cat F | sort -o F'. However, `sort' with `--merge' (`-m')
can open the output file before reading all input, so a command
like `cat F | sort -m -o F - G' is not safe as `sort' might start
writing `F' before `cat' is done reading it.
On newer systems, `-o' cannot appear after an input file if
`POSIXLY_CORRECT' is set, e.g., `sort F -o F'. Portable scripts
should specify `-o OUTPUT-FILE' before any input files.
et de The Open Group Base Specifications Issue 7 :
-o output
Specify the name of an output file to be used instead of the standard
output. This file can be the same as one of the input files.
Vous pouvez utiliser la fonction sponge
, qui imprègne d'abord le stdin
puis l'écrit dans un fichier, comme:
sort < f | sponge f
L'inconvénient de sponge
est qu'il stockera la sortie temporaire en mémoire, ce qui peut être problématique pour les gros fichiers. Sinon, vous devez d'abord l'écrire dans un fichier, puis écraser le fichier d'origine.
Comme cela est cependant souligné par d'autres réponses, les modifications sur place ne sont généralement pas une bonne idée, car au milieu d'un processus (par exemple, sponge
), la machine peut se bloquer et vous pouvez alors perdre les deux le fichier original et nouveau. Vous feriez mieux de l'écrire d'abord dans un fichier différent, puis d'utiliser une instruction atomique mv
(move).
Il est dangereux d'écraser le fichier d'entrée par le fichier de sortie, car si le programme ou le système se bloque pendant l'écriture du fichier, vous avez perdu les deux.
Quelques programmes (principalement GNU) ont une option sur place (par exemple -i
sur Perl et GNU sed; -o
on GNU). Ils travaillent en plaçant les données dans un fichier temporaire puis en les déplaçant en place. Pour les programmes qui n'ont pas une telle option, tilitaire sponge
de Colin Watson (inclus dans Moreutils de Joey Hess ) fait le travail en toute sécurité pour n'importe quel programme (exemples: - Puis-je faire cut
changer un fichier en place? ; Comment puis-je faire iconv remplacer le fichier d'entrée par la sortie convertie? ).
Ce n'est que dans les rares cas où vous ne pouvez pas recréer le fichier d'origine avec les mêmes autorisations que je recommande d'écraser le fichier en place. Dans ce cas, vous feriez mieux d'enregistrer l'entrée d'origine quelque part. Et puis, vous pouvez simplement traiter la copie de l'entrée et l'envoyer dans le fichier d'origine.
cp -p f ~/f.backup
sort <~/f.backup >|f
rm ~/f.backup # optional
Utilisation -o
ou essayez le vim-way:
$ ex -s +'%!sort' -cxa file.txt