web-dev-qa-db-fra.com

Le tri prend-il en charge le tri d'un fichier sur place, comme `sed --in-place`?

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.)

89

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.
123
enzotib

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).

11
Willem Van Onsem

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
4
kenorb