Apagar primeiro 10 linhas de vários arquivos [duplicado]

4

Os arquivos são denominados file00 a file99 (cem arquivos). Eles estão todos no mesmo diretório. Como faço para pegar todos os cem arquivos e excluir as 10 primeiras linhas de cada arquivo? Eu estou usando o CentOS 7.

    
por stackoverflowpro 31.07.2016 / 08:52

4 respostas

4

Isso excluirá as dez primeiras linhas de todos os arquivos cujos nomes variam de file00 a file99 :

sed -i.bak -n '11,$p' file[0-9][0-9]

Isso pode exigir o GNU sed , que é conhecido como gsed no OSX. Para outros seds, tente:

find file[0-9][0-9] -maxdepth 0 -type f -exec sed -i.bak -n '11,$p' {} \;

Como funciona:

  1. -i.bak informa ao sed para modificar os arquivos no local, criando um arquivo de backup com a extensão .bak

  2. -n diz ao sed para não imprimir nenhuma linha, a menos que seja explicitamente solicitada.

  3. 11,$p informa ao sed para imprimir linhas iniciando com o número de linha 11 e continuando até a última linha (denotada $ ) no arquivo.

  4. file[0-9][0-9] é um shell glob que será expandido para corresponder a todos os arquivos cujos nomes consistam em file seguido por dois dígitos.

Alternativa

A lógica pode ser invertida. Em vez de imprimir explicitamente as linhas 11 e depois, poderíamos (dica: JigglyNaga) excluir as dez primeiras linhas:

sed -i.bak '1,10d' file[0-9][0-9]
    
por 31.07.2016 / 09:27
4

Usando um loop simples em bash (ou qualquer shell parecido com o Bourne) e GNU ou BSD sed :

for f in file[0-9][0-9]; do
  sed -i '.bak' '1,10d' "$f"
done

O script sed de edição 1,10d excluirá as linhas de 1 a 10 do fluxo de entrada. As outras linhas serão produzidas. Com -i '.bak' , pedimos que sed faça a edição em linha no arquivo, mas faça o backup do original com um sufixo .bak .

Alternativas com looping explícito (permite subintervalos, ksh93 , bash ou zsh sintaxe):

for (( i = 0; i < 100; ++i )); do
  f="$( printf "file%02d" "$i" )"
  sed -i '.bak' '1,10d' "$f"
done

Usando ksh93 ou zsh , de outra forma:

typeset -Z 2 j
for (( i = 0; i < 100; ++i )); do
  j=$i
  sed -i '.bak' '1,10d' "file$j"
done

O typeset -Z 2 j forçará $j em um número preenchido com zero de largura 2. Não queremos typeset i dessa forma, pois seu valor se transformaria em 00 quando atingisse 100 , efetivamente transformando o loop em um loop infinito. Isso é para ksh93 , zsh parece ser capaz de lidar com isso, já que aparentemente usa o valor antes de enviá-lo para a formatação.

    
por 31.07.2016 / 09:37
3

Para evitar criar arquivos temporários ou afetar as permissões, propriedade ou outros atributos dos arquivos, com ksh93 :

for f in file{2}([0-9]); do
  tail -n +11 < "$f" 1<>; "$f"
done

O operador de redirecionamento <>; age como <> (aberto no modo de leitura + gravação), exceto pelo fato de que o shell trunca o arquivo quando o comando sai com êxito na posição que o comando deixou.

Então, basicamente sobrescrevemos o arquivo sobre ele mesmo.

    
por 31.07.2016 / 17:30
2

Se você preferir um loop bash:

for f in file[0-9][0-9]; do
    tail -n +11 "$f" > tmp &&
    mv -f tmp "$f"
done
    
por 31.07.2016 / 10:09

Tags