Script Bash para imprimir arquivos com um determinado comprimento de linha

3

Sou novo nisso ... Preciso de um script que receba um diretório como parâmetro e imprima os nomes de arquivos que tenham entre 15 e 50 linhas, mas não sei como usar a saída wc em um if -sentence:

#!/bin/bash
for f in 'ls'; do
  echo "File -> $f"
  cat $f | wc -l
done

Como recebo um parâmetro? E como atribuo a wc output a uma variável?

    
por jaundavid 19.07.2013 / 18:19

3 respostas

7

Os parâmetros podem ser recebidos como $1 , $2 , etc. ou $* para todos eles.

Há também a matriz $@ , que geralmente é usada como "$@" como uma versão melhor de $* . Outro uso possível é ${@:3} , que significa "todos os argumentos começando com o terceiro".

Para obter a saída de um comando, use $( ... ) ou sua forma antiga ' ... ' . Geralmente, é recomendável sempre usar $() , já que ele pode ser aninhado, por exemplo, blah=$(cat /blah/$(blah)/blah) .

#!/usr/bin/env bash

for dir in "$@"; do
    for file in "$dir"/*; do
        lines=$(wc -l < "$file")
        if (( lines >= 15 && lines <= 50 )); then
            echo "File -> $file ($lines lines)"
        fi
        # another possible syntax:
        # if [ "$lines" -ge 15 ] && [ "$lines" -le 50 ]
        # or:
        # if [[ "$lines" -ge 15 && "$lines" -le 50 ]]
    done
done

Recursos úteis:

por 19.07.2013 / 18:32
3

Aqui está outra maneira de fazer isso usando awk :

#!/usr/bin/env bash
for dir in "$@"; do
  for file in "$dir"/*; do 
    awk 'END{if(NR>=15 && NR<=50){print FILENAME}}' "$file"; 
  done
done

EXPLICAÇÃO: awk (e suas muitas variantes como gawk ou mawk etc) leem um arquivo linha por linha. A variável NR é o número da linha atual. Um bloco END{} será executado quando a última linha do arquivo de entrada for atingida, altura em que NR será o número de lnes no arquivo. Finalmente, FILENAME é o nome do arquivo atualmente sendo processado. Então, o script imprime o nome do arquivo se o número de linhas que ele viu estiver entre 15 e 50.

Da mesma forma, você pode fazer isso com o Perl:

#!/usr/bin/env bash
for dir in "$@"; do
  for file in "$dir"/*; do 
      perl -ne 'END{if($. >=15 && $. <=50){print "$ARGV\n"}}' "$file"
  done
done

EXPLICAÇÃO: perl -ne também lerá um arquivo linha por linha. Em Perl, o número da linha atual é armazenado em $. e o bloco END funciona da mesma maneira que em awk . $ARGV é o argumento transmitido na linha de comando, o nome do arquivo que será impresso apenas se tiver o número correto de linhas.

Sua melhor escolha provavelmente será o bash e wc responda do @grawity, mas eles não serão afetados por a implementação wc e deve rodar bem em qualquer * nix.

    
por 19.07.2013 / 19:12
2

Gere alguns arquivos:

$ for i in 'seq -w 1 60'; do seq -w 1 $i > $i.lines; done

Imprima apenas aqueles que atendem aos critérios:

$ wc -l * | awk '$1 >= 15 && $1 <= 50 { print $2 }' | column
15.lines        23.lines        31.lines        39.lines        47.lines
16.lines        24.lines        32.lines        40.lines        48.lines
17.lines        25.lines        33.lines        41.lines        49.lines
18.lines        26.lines        34.lines        42.lines        50.lines
19.lines        27.lines        35.lines        43.lines
20.lines        28.lines        36.lines        44.lines
21.lines        29.lines        37.lines        45.lines
22.lines        30.lines        38.lines        46.lines
    
por 19.07.2013 / 23:53

Tags