Eu tenho um arquivo temp.txt, que desejo classificar com o sort
comando em bash.
Quero que os resultados classificados substituam o arquivo original.
Isso não funciona, por exemplo (recebo um arquivo vazio):
sortx temp.txt > temp.txt
Isso pode ser feito em uma linha sem recorrer à cópia para arquivos temporários?
EDIT: A -o
opção é muito legal para sort
. Usei sort
na minha pergunta como exemplo. Eu tenho o mesmo problema com outros comandos:
uniq temp.txt > temp.txt.
Existe uma solução geral melhor?
bash
command-line
sorting
jm.
fonte
fonte
Respostas:
fonte
sort --inplace *.txt
? Isso seria muito legalfind . -name \*.txt -exec sort {} -o {} \;
A
sort
precisa ver todas as entradas antes de começar a produzir. Por esse motivo, osort
programa pode facilmente oferecer uma opção para modificar um arquivo no local:Especificamente, a documentação do GNU
sort
diz:Enquanto a documentação do BSD
sort
diz:Comandos como
uniq
podem começar a gravar a saída antes de terminarem de ler a entrada. Normalmente, esses comandos não oferecem suporte à edição local (e seria mais difícil para eles oferecer suporte a esse recurso).Normalmente, você contorna isso com um arquivo temporário ou, se deseja absolutamente evitar um arquivo intermediário, pode usar um buffer para armazenar o resultado completo antes de gravá-lo. Por exemplo, com
perl
:Aqui, a parte perl lê a saída completa da
uniq
variável$_
e sobrescreve o arquivo original com esses dados. Você pode fazer o mesmo na linguagem de script de sua escolha, talvez até mesmo no Bash. Mas observe que será necessária memória suficiente para armazenar o arquivo inteiro, isso não é aconselhável ao trabalhar com arquivos grandes.fonte
Aqui está uma abordagem mais geral, funciona com uniq, sort e outros enfeites.
fonte
sponge
dos moreutils:cat file |frobnicate |sponge file
.O comentário de Tobu sobre a esponja justifica ser uma resposta por si só.
Para citar a página inicial do moreutils :
No entanto,
sponge
sofre do mesmo problema que Steve Jessop comenta aqui. Se qualquer um dos comandos do pipelinesponge
falhar antes , o arquivo original será sobrescrito.Uh-oh,
my-important-file
sumiu.fonte
set -o pipefail
no início do seu script, o erro emmistyped_command my-important-file
faria o script sair imediatamente, antes de ser executadosponge
, preservando assim o arquivo importante.Aqui está, uma linha:
Tecnicamente, não há cópia para um arquivo temporário e o comando 'mv' deve ser instantâneo.
fonte
Gosto da
sort file -o file
resposta, mas não quero digitar o mesmo nome de arquivo duas vezes.Usando a expansão da história do BASH :
pega o primeiro argumento da linha atual quando você pressiona enter.
Uma classificação única no local:
pega o último argumento na linha atual.
fonte
Muitos mencionaram o -o opção . Aqui está a parte da página do manual.
Na página de manual:
fonte
Isso seria altamente limitado pela memória, mas você poderia usar o awk para armazenar os dados intermediários na memória e, em seguida, gravá-los novamente.
fonte
>
trunca o arquivo antes do comando (uniq
neste caso) lê-lo.Uma alternativa ao
sponge
mais comumsed
:Ele funciona para qualquer comando (
sort
,uniq
,tac
, ...) e usa o bem conhecidosed
's-i
opção (editar arquivos no local).Aviso: tente
command file
primeiro porque editar arquivos no local não é seguro por natureza.Explicação
Em primeiro lugar, você está dizendo
sed
não para imprimir a linhas (original) (-n
opção ), e com a ajuda dosed
'sr
comando ebash
do processo de substituição , o conteúdo gerado pelo<(command file)
será a saída salva no lugar .Tornando as coisas ainda mais fáceis
Você pode envolver esta solução em uma função:
Exemplo
fonte
Use o argumento
--output=
ou-o
Tentei no FreeBSD:
fonte
Para adicionar a
uniq
capacidade, quais são as desvantagens de:fonte
Leia no editor não interativo
ex
,.fonte
Se você insiste em usar o
sort
programa, tem que usar um arquivo intermediário - não acho quesort
tenha uma opção de ordenação na memória. Qualquer outro truque com stdin / stdout falhará, a menos que você possa garantir que o tamanho do buffer para stdin do sort é grande o suficiente para caber no arquivo inteiro.Editar: vergonha para mim.
sort temp.txt -o temp.txt
funciona excelente.fonte
Outra solução:
fonte
<>
truque só funciona neste caso porqueuniq
é especial porque ele apenas copia as linhas de entrada para linhas de saída, deixando algumas no caminho. Se outro comando (por exemplosed
) foi usado que mudaria a entrada (por exemplo, mudaria todosa
emaa
), então ele pode substituirfile
de maneiras que não fazem nenhum sentido e até mesmo fazer um loop infinito, desde que a entrada seja suficientemente grande (mais de um buffer de leitura único).