Como posso excluir uma parte fixa de algumas linhas de um arquivo de texto?

3

Eu tenho usado o ls -Rlh /path/to/directory > file para criar alguns registros de arquivos de texto do que há em alguns discos rígidos.

Eu quero excluir algumas seqüências de caracteres dos arquivos de texto depois que eles forem criados.

Um exemplo de parte de um arquivo de texto é:

external1:
total 36K
drwxrwxr-x 2 emma emma 4.0K Oct 31 01:29 dir1
drwxrwxr-x 2 emma emma  12K Oct 31 01:29 dir2
drwxrwxr-x 2 emma emma  20K Oct 31 01:29 dir3

external1/dir1:
total 4.5M
-rw-rw-r-- 1 emma emma 769K Oct 31 01:12 a001.jpg
-rw-rw-r-- 1 emma emma 698K Oct 31 01:12 a002.jpg
-rw-rw-r-- 1 emma emma 755K Oct 31 01:12 a003.jpg
-rw-rw-r-- 1 emma emma 656K Oct 31 01:12 a004.jpg
-rw-rw-r-- 1 emma emma 756K Oct 31 01:12 a005.jpg
-rw-rw-r-- 1 emma emma 498K Oct 31 01:12 a006.jpg
-rw-rw-r-- 1 emma emma 455K Oct 31 01:12 a007.jpg

external1/dir2:
total 8.7M
-rw-rw-r-- 1 emma emma  952K Oct 31 01:13 a001.jpg
-rw-rw-r-- 1 emma emma  891K Oct 31 01:13 a002.jpg
-rw-rw-r-- 1 emma emma  838K Oct 31 01:13 a003.jpg
-rw-rw-r-- 1 emma emma  846K Oct 31 01:13 a004.jpg
-rw-rw-r-- 1 emma emma  876K Oct 31 01:13 a005.jpg
-rw-rw-r-- 1 emma emma  834K Oct 31 01:13 a006.jpg
-rw-rw-r-- 1 emma emma  946K Oct 31 01:13 a007.jpg
-rw-rw-r-- 1 emma emma  709K Oct 31 01:13 a008.jpg
-rw-rw-r-- 1 emma emma 1007K Oct 31 01:13 a009.jpg
-rw-rw-r-- 1 emma emma  940K Oct 31 01:13 a010.jpg

external1/dir3:
total 4.6M
-rw-rw-r-- 1 emma emma 408K Oct 31 01:15 a001.jpg
-rw-rw-r-- 1 emma emma 525K Oct 31 01:15 a002.jpg
-rw-rw-r-- 1 emma emma 383K Oct 31 01:15 a003.jpg
-rw-rw-r-- 1 emma emma 512K Oct 31 01:15 a004.jpg
-rw-rw-r-- 1 emma emma 531K Oct 31 01:15 a005.jpg
-rw-rw-r-- 1 emma emma 532K Oct 31 01:15 a006.jpg
-rw-rw-r-- 1 emma emma 400K Oct 31 01:15 a007.jpg
-rw-rw-r-- 1 emma emma 470K Oct 31 01:15 a008.jpg
-rw-rw-r-- 1 emma emma 407K Oct 31 01:15 a009.jpg
-rw-rw-r-- 1 emma emma 470K Oct 31 01:15 a010.jpg

Os arquivos de texto reais têm milhares de linhas de comprimento e vários megabytes de tamanho.

O que eu quero fazer é excluir tudo antes do tamanho do arquivo de cada linha aplicável, para que cada linha comece com o tamanho do arquivo. Por exemplo,

512K Oct 31 01:15 a004.jpg
531K Oct 31 01:15 a005.jpg
532K Oct 31 01:15 a006.jpg
400K Oct 31 01:15 a007.jpg
470K Oct 31 01:15 a008.jpg

No entanto, quero manter todas as outras linhas (com os nomes dos diretórios e os tamanhos totais) intactas. Isso significa que não posso usar colrm ou cut .

    
por EmmaV 31.10.2015 / 03:07

3 respostas

4

analisar a saída de ls não é confiável, mas isso deve funcionar neste caso específico:

sed -e 's/^.*emma emma //' file

Isso exclui tudo para "emma emma" em cada linha. se essa string não aparecer em uma linha, ela não será alterada.

Eu escrevi o regexp para remover somente o primeiro espaço após o emma, para que o campo de tamanho permaneça alinhado à direita (por exemplo, '709K' e '1007K', ambos usam a mesma quantidade de caracteres na linha)

se você não quiser, use isso:

sed -e 's/^.*emma emma  *//' file

que apagará todos os espaços em branco após o emma até o início do próximo campo.

Aqui está uma versão sed que funciona com qualquer user group :

sed -e 's/^.\{10\} [0-9]\+ [^ ]\+ [^ ]\+ //' file

ele depende ainda mais do formato exato da sua saída ls , portanto, é tecnicamente ainda pior do que a primeira versão .... mas deve funcionar para o seu arquivo em particular.

veja Por que * not * ls '? para informações sobre por que a análise ls é ruim.

Se nem todos os arquivos forem de propriedade de emma , convém usar um script awk como este.

awk 'NF>2 {print $5,$6,$7,$8,$9} ; NF<3 {print}' file

Para linhas com mais de 2 campos, imprime apenas os campos 5-9. para linhas com campos < 3, imprime a linha inteira. infelizmente, isso perde o alinhamento à direita do campo de tamanho .... que pode ser corrigido com um script awk um pouco mais complicado:

awk 'NF>2 {printf "%5s %s %s %s %s\n", $5, $6, $7, $8, $9} ; NF<3 {print}' file 

Esta versão final mescla o loop for da resposta de jasonwryan, então lida com nomes de arquivos que possuem qualquer número de espaços simples neles (mas não espaços consecutivos, como mencionado por G-Man):

awk 'NF>2 {printf "%5s", $5; for(i=6;i<=NF;i++){printf " %s", $i}; printf "\n"} ; NF<3 {print}' file 
    
por 31.10.2015 / 03:12
2

Usando o Awk:

awk '{if ($1 ~/^-|d/) {for(i=5;i<=NF;i++){printf "%s ", $i}; printf "\n"} else print $0}' file

Se o primeiro campo começar com - ou d ; depois imprima do quinto ao campo final, caso contrário, imprima o registro inteiro.

    
por 31.10.2015 / 03:22
1

Como você fala sobre 100s de MB de dados, pode valer a pena usar as opções -o e -g do gnu ls para evitar a impressão do usuário e do grupo, resultando neste formato:

-rw-rw-r-- 1 952K Oct 31 01:13 a001.jpg

Este comando sed removerá os dados indesejados no início da linha:

sed 's/^[-a-z]{10} \{1,\}[0-9]\{1,\}//'

Você pode combinar a listagem e a remoção de dados desnecessários em uma etapa (isso também se aplica à maioria das soluções nesta página), o que também pode economizar algum tempo:

ls -Rlhog /path/to/directory | sed 's/^[-a-z]\{10\} \{1,\}[0-9]\{1,\}//' > file
    
por 31.10.2015 / 05:31