L'ordinamento supporta l'ordinamento di un file sul posto, come `sed --in-place`?


80

Sono cieco o non esiste un'opzione come --in-placeper sort?

Per salvare i risultati nel file di input, sed usa -i( --in-place).

Reindirizzare l'output di sortal file di input

sort < f > f

risulta vuoto. Se non c'è alcuna --in-placeopzione, forse c'è qualche trucco come farlo in modo pratico ?

(L'unica cosa che mi viene in mente:

sort < f > /tmp/f$$ ; cat /tmp/f$$ > f ; rm /tmp/f$$

Lo spostamento non è la scelta giusta, poiché le autorizzazioni dei file potrebbero essere modificate. Ecco perché sovrascrivo con il contenuto del file temporaneo che rimuovo.)


C'è anche insitu, consentendo qualsiasi comando da utilizzare sul posto.
sr_

@sr_, è un comando interessante, ma non funziona con nessun comando, solo quelli che non scrivono più velocemente di quanto leggano (altrimenti bloccherà il file di input prima che il comando lo legga). Non c'è garanzia che funzioni con sort.
cjm

@cjm, non ne sono davvero sicuro, ma questo non dovrebbe occuparsi di quel caso?
sr_

@sr_, penso che tu abbia ragione. Ho letto la descrizione invece di guardare la fonte. Anche se per file molto grandi, potrebbe esaurire la memoria per il buffer e l'arresto anomalo (non sembra che controlli un ritorno NULL da malloc).
cjm

@cjm: Oh sì, davvero.
sr_

Risposte:


110

sortha l' -o, --outputopzione che accetta un nome file come argomento. Se è uguale al file di input, scrive il risultato in un file temporaneo, quindi sovrascrive il file di input originale (esattamente la stessa cosa di quello che sed -ifa).

Dalla GNU sortpagina informativa:

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

e da The Open Group Base Issues 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.

Esattamente ! Funziona ! Non riesco a vedere alcun indizio al riguardo man sort- è una funzionalità non documentata? È standard e portatile?
Grzegorz Wierzowiecki,

@GrzegorzWierzowiecki: vedi aggiornamento.
enzotib,

Bella risposta :).
Grzegorz Wierzowiecki,

1
In sintesi: sort -o <filename> <filename>ordinerà in modo sicuro un file in atto.
phyatt

11

È possibile utilizzare la spongefunzione, che prima assorbe stdine quindi la scrive in un file, come:

sort < f | sponge f

L'aspetto negativo di spongeè che memorizzerà l'output temporaneo in memoria, che può essere problematico per file di grandi dimensioni. Altrimenti devi prima scriverlo su un file e poi sovrascrivere il file originale.

Come tuttavia sottolineato da altre risposte, in genere le modifiche non sono una buona idea, poiché nel mezzo di un processo (ad esempio spongequello), la macchina potrebbe arrestarsi in modo anomalo e quindi perdere sia il file originale che quello nuovo. È meglio prima scriverlo su un altro file e quindi utilizzare un'istruzione atomica mv(sposta).


7

È pericoloso sovrascrivere il file di input con il file di output, perché se il programma o il sistema si arresta in modo anomalo durante la scrittura del file, hai perso entrambi.

Alcuni programmi (principalmente versioni GNU) hanno un'opzione sul posto (ad es. -iSu perl e GNU sed; -osu GNU sort). Funzionano mettendo i dati in un file temporaneo e poi spostandoli in posizione. Per i programmi che non hanno tale opzione, di Colin Watson spongeutilità (inclusa nel moreutils di Joey Hess ) fa il lavoro in modo sicuro per qualsiasi programma (esempi: posso fare cut? Modificare un file sul posto ; Come posso fare iconv sostituire il file di input con il convertito uscita? ).

Solo in quei rari casi in cui non è possibile ricreare il file originale con le stesse autorizzazioni, consiglio di sovrascrivere il file in atto. In questo caso, è meglio salvare l'input originale da qualche parte. E quindi puoi semplicemente elaborare la copia dell'input e inviarlo nel file originale.

cp -p f ~/f.backup
sort <~/f.backup >|f
rm ~/f.backup # optional

1
sort -onon è specifico per GNU ed è appositamente progettato per sovrascrivere il file in atto. sortnon può iniziare a scrivere il suo output prima che abbia letto completamente i suoi input (usa la memoria o i file temporanei per archiviare i dati), quindi è abbastanza naturale che dovrebbe essere in grado di sovrascriverne l'input.
Stéphane Chazelas,

E in realtà, è un caso in cui GNU sortnon è POSIX in quanto sort -mo file1 file1 file2non è garantito che funzioni mentre i tradizionali sortsanno come aggirare il problema (già in Unix V7 negli anni '70).
Stéphane Chazelas,

@JoelCross Odd, sort -ofunziona per me con coreutils 8.25 e la proprietà è documentata nel manuale (notando che è solo il caso durante l'ordinamento, non durante l'unione). Se riesci a riprodurlo, invia una segnalazione di bug (indicando la riga di comando esatta, i file di input esatti, il sistema su cui lo stai eseguendo e come hai ottenuto il binario).
Gilles,

4

Usa -oo prova la vim-way:

$ ex -s +'%!sort' -cxa file.txt
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.