A classificação suporta a classificação de um arquivo no local, como `sed - in-place`?


80

Sou cego ou não existe uma opção --in-placepara isso sort?

Para salvar os resultados no arquivo de entrada, sed usa -i( --in-place).

Redirecionando a saída sortpara o arquivo de entrada

sort < f > f

resulta em torná-lo vazio. Se não houver --in-placeopção - talvez haja algum truque para fazer isso de maneira prática ?

(A única coisa que me vem à cabeça:

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

Mover não é a escolha certa, pois as permissões do arquivo podem ser alteradas. É por isso que sobrescrevo o conteúdo do arquivo temporário que removo.)


Também existe insitu, permitindo que qualquer comando seja usado no local.
sr_

@sr_, esse é um comando interessante, mas não funciona com nenhum comando, apenas aqueles que escrevem não mais rápido do que lêem (caso contrário, ele estraga o arquivo de entrada antes que o comando o leia). Não há garantia de que funcione sort.
Cjm

@ CCJ, eu realmente não tenho certeza, mas isso não deveria lidar com esse caso?
sr_

@sr_, acho que você está certo. Eu li a descrição em vez de olhar para a fonte. Embora para arquivos realmente grandes, ele pode ficar sem memória para o buffer e travar (não parece que ele procura um retorno NULL do malloc).
Cjm

@ cjm: Ah, sim, de fato.
sr_

Respostas:


110

sorttem a -o, --outputopção que aceita um nome de arquivo como argumento. Se for o mesmo que o arquivo de entrada, ele grava o resultado em um arquivo temporário e substitui o arquivo de entrada original (exatamente o mesmo que o que sed -ifaz).

Na GNU sortpágina de informações:

`-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 do The Open Group Base Specifications Edição 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.

Exatamente ! Funciona ! Não vejo nenhuma pista sobre isso man sort- é um recurso não documentado? É padrão e portátil?
Grzegorz Wierzowiecki 22/01

@GrzegorzWierzowiecki: veja atualização.
enzotib

Boa resposta :).
Grzegorz Wierzowiecki 22/01

1
Em resumo: sort -o <filename> <filename>irá classificar com segurança um arquivo no local.
Phyatt #

11

Você pode usar a spongefunção, que primeiro absorve stdine depois a grava em um arquivo, como:

sort < f | sponge f

A desvantagem spongeé que ele armazenará a saída temporariamente na memória, o que pode ser problemático para arquivos grandes. Caso contrário, você deve gravá-lo em um arquivo primeiro e depois substituir o arquivo original.

Como, no entanto, é apontado por outras respostas, as modificações no local geralmente não são uma boa ideia, pois no meio de um processo (por exemplo, o processo sponge), a máquina pode travar e você pode perder o arquivo original e o novo. É melhor primeiro gravá-lo em um arquivo diferente e depois usar uma mvinstrução atômica (mover).


7

É perigoso substituir o arquivo de entrada pelo arquivo de saída, porque se o programa ou o sistema travar enquanto o arquivo está sendo gravado, você perdeu os dois.

Alguns programas (principalmente versões do GNU) têm uma opção no local (por exemplo, -ino perl e GNU sed; -ono tipo GNU). Eles trabalham colocando os dados em um arquivo temporário e depois movendo-os para o lugar. Para programas que não têm essa opção, o spongeutilitário de Colin Watson (incluído no moreutils de Joey Hess ) realiza o trabalho com segurança em qualquer programa (exemplos: posso cutalterar um arquivo no local ?; Como faço para o iconv substituir o arquivo de entrada pelo arquivo convertido saída? ).

Somente nos casos raros em que você não pode recriar o arquivo original com as mesmas permissões é recomendável substituir o arquivo no local. Nesse caso, é melhor salvar a entrada original em algum lugar. E então você pode simplesmente processar a cópia da entrada e enviá-la para o arquivo original.

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

1
sort -onão é específico do GNU e foi especialmente desenvolvido para substituir o arquivo no local. sortnão pode começar a gravar sua saída antes de ler completamente suas entradas (usa memória ou arquivos temporários para armazenar dados); portanto, é natural que ele possa substituir sua entrada.
Stéphane Chazelas

E, na verdade, é um caso em que o GNU sortnão é POSIX, pois sort -mo file1 file1 file2não é garantido que funcione enquanto os sorts tradicionais sabem como solucionar isso (já lido no Unix V7 nos anos 70).
Stéphane Chazelas

O @JoelCross Odd, sort -ofunciona para mim com o coreutils 8.25 e a propriedade está documentada no manual (observando que esse é apenas o caso na classificação e não na mesclagem). Se você pode reproduzir isso, envie um relatório de erro (indicando a linha de comando exata, o (s) arquivo (s) de entrada exato (s), em que sistema você o está executando e como obteve o binário).
Gilles

4

Use -oou tente o vim-way:

$ ex -s +'%!sort' -cxa file.txt
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.