Eu tenho muitos arquivos de texto em um diretório e quero remover a última linha de todos os arquivos no diretório.
Como eu posso fazer isso?
text-processing
files
ThehalfarisedPheonix
fonte
fonte
Respostas:
Se você tiver acesso
vim
, poderá usar:fonte
Você pode usar este bom oneliner se tiver o GNU
sed
.Ele removerá a última linha de cada arquivo não oculto no diretório atual. Mudar
-i
para GNUsed
significa operar no lugar e'$ d'
comandar ased
exclusão da última linha (que$
significa última e qued
significa excluir).fonte
-i
que é um GNUism, então isso é discutível, mas eu perderia minha barba antiga se deixasse de ressaltar que algumas versões mais antigassed
do não permitem que você coloque espaço em branco entre o$
e od
(ou, em geral, entre o padrão e o comando).*(.)
glob para arquivos regulares, não sei sobre outros shells.As outras respostas têm problemas se o diretório contiver algo diferente de um arquivo comum ou um arquivo com espaços / novas linhas no nome do arquivo. Aqui está algo que funciona independentemente:
find "$dir" -type f
: encontre os arquivos no diretório$dir
-type f
que são arquivos regulares;-exec
execute o comando em cada arquivo encontradosed -i
: edite os arquivos no local;'$d'
: delete (d
) o último ($
) linha.'+'
: diz ao find para continuar adicionando argumentossed
(um pouco mais eficiente do que executar o comando para cada arquivo separadamente, graças a @zwol).Se você não desejar descer para subdiretórios, poderá adicionar o argumento
-maxdepth 1
afind
.fonte
find
presente é mais eficiente escritofind $dir -type f -exec sed -i '$d' '{}' '+'
.)-print0
não está presente no comando completo, por que colocá-lo na explicação?-depth 0
não funciona (findutils 4.4.2), deveria ser-maxdepth 1
.-exec
.Usar o GNU
sed -i '$d'
significa ler o arquivo completo e fazer uma cópia dele sem a última linha, enquanto seria muito mais eficiente truncar o arquivo no local (pelo menos para arquivos grandes).Com o GNU
truncate
, você pode fazer:Se os arquivos forem relativamente pequenos, isso provavelmente seria menos eficiente, pois ele executa vários comandos por arquivo.
Observe que, para arquivos que contenham bytes extras após o último caractere de nova linha (após a última linha) ou em outras palavras, se eles tiverem uma última linha não delimitada , dependendo da
tail
implementação,tail -n 1
retornará apenas esses bytes extras (como GNUtail
), ou a última linha (delimitada corretamente) e esses bytes extras.fonte
|wc -c
natail
chamada? (ou a${#length}
)${#length}
não funcionaria, pois conta caracteres, não bytes, e$(...)
removeria o caractere de nova linha posterior${#...}
, sendo desativado em um, mesmo que todos os caracteres fossem de byte único.Uma abordagem mais portátil:
Eu não acho que isso precisa qualquer explicação ... exceto, talvez, que neste caso
d
é o mesmo que$d
uma vezed
por seleciona padrão a última linha.Isso não procurará recursivamente e não processará arquivos ocultos (também conhecidos como dotfiles).
Se você também deseja editá-los, consulte Como combinar * com arquivos ocultos em um diretório
fonte
[[]]
para[]
, será totalmente compatível com POSIX. ([[ ... ]]
é um Bashism).[[
não seja um Bashismo )Uma linha compatível com POSIX para todos os arquivos que começam recursivamente no diretório atual, incluindo arquivos de ponto:
Apenas para
.txt
arquivos, de forma não recursiva:Veja também:
fonte