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

68

Sou cego ou não há opção como --in-place para sort ?

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

Redirecionando a saída de sort para o arquivo de entrada

sort < f > f

resulta em esvaziá-lo. Se não houver uma opção --in-place - talvez haja algum truque de como fazer isso de uma maneira acessível ?

(A única coisa que me vem à mente:

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

A mudança não é a escolha certa, porque as permissões de arquivo podem ser alteradas. É por isso que eu sobrescrevo o conteúdo do arquivo temporário que eu removo.)

    
por Grzegorz Wierzowiecki 22.01.2012 / 11:02

4 respostas

92

sort tem a opção -o, --output que usa 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 sobrescreve o arquivo de entrada original (exatamente a mesma coisa que sed -i faz).

Da página de informações de GNU sort :

'-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 de Especificações do Grupo Open de Base 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.
    
por 22.01.2012 / 11:10
7

É perigoso sobrescrever o arquivo de entrada com o arquivo de saída, porque se o programa ou o sistema travar enquanto o arquivo está sendo gravado, você perdeu ambos.

Alguns programas (principalmente versões GNU) têm uma opção no local (por exemplo, -i no perl e GNU sed; -o no GNU sort). Eles trabalham colocando os dados em um arquivo temporário e, em seguida, movendo-o para o lugar. Para programas que não têm tal opção, sponge utility de Colin Watson (incluído em moreutils de Joey Hess ) faz o trabalho com segurança para qualquer programa (exemplos: Posso fazer cut alterar um arquivo no lugar? ; Como posso fazer o iconv substituir o arquivo de entrada pela saída convertida? ).

Apenas nos casos raros em que não é possível recriar o arquivo original com as mesmas permissões, recomendo que você substitua o arquivo. 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
    
por 23.01.2012 / 01:13
7

Você pode usar a função sponge , que primeiro absorve o stdin e o grava em um arquivo, como:

sort < f | sponge f

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

Como é apontado por outras respostas, modificações em geral não são uma boa idéia, já que no meio de um processo (por exemplo o sponge one), a máquina pode falhar e você pode perder ambos o arquivo original e novo. É melhor escrever primeiro em um arquivo diferente e usar uma instrução atômica mv (move).

    
por 20.04.2015 / 09:47
4

Use -o ou tente o vim-way:

$ ex -s +'%!sort' -cxa file.txt
    
por 19.04.2015 / 22:49