Como obtenho uma contagem de referências de arquivos dentro de uma pasta de arquivos com essas referências?

1

Tudo bem, tenho duas pastas. Para simplificar, vou chamá-los de people e animals . A pasta de animais tem um arquivo para cada animal, e a pasta de pessoas tem um arquivo para cada pessoa com referências a quais animais essa pessoa possui. Isso é o que eu tenho até agora:

ls -1 ~/animals | cut -d. -f1 | grep -R -f - ~/people

A sintaxe do grep que recebi de aqui . Estou tentando dizer:

dog: 8
cat: 7
hippo: 2

Em vez disso, adiciono o sinal -c a grep e obtenho:

Bob.txt: 0
Cathy.txt: 0
John.txt: 0
Patrick.txt: 1

Como obtenho contagens dos animais no total, não os animais para cada pessoa?

    
por NobleUplift 26.04.2015 / 06:55

2 respostas

1

Esta é uma maneira de obter os resultados desejados com o GNU awk :

awk '
    BEGINFILE {
        if (FILENAME ~ "^animals/"  ||  FILENAME ~ "/animals/") {
                this_name = substr(FILENAME, index(FILENAME,"animals/")+length("animals/"))
                i = index(this_name, ".")
                if (i > 0) this_name = substr(this_name, 1, i-1)
                critter[++num] = this_name
                critter_count[num] = 0
                nextfile
        }
    }
    {
        for (i = 1; i <= num; i++) {
                if ($0 ~ critter[i]) critter_count[i]++
        }
    }
    END {
        for (i = 1; i <= num; i++) print critter[i] ": " critter_count[i]
    }
'  animals/*  people/*
  • Ao iniciar um novo arquivo ( BEGINFILE ), verifique se o nome começa com animals/ ou contém /animals/ . Isso permite que você diga animals/* , ./animals/* ou ~/animals/* . Se isso acontecer,

    • Extraia a substring à direita de animals/ .
    • Em seguida, procure por . ; se encontrado, extraia a substring à esquerda dele.
    • Adicione esta string (o nome do arquivo base, com o diretório e a extensão removidos) para a matriz critter[] , e inicialize o critter_count correspondente a 0.

    ☛ Observe que BEGINFILE e nextfile não estão disponíveis no POSIX awk.

  • Caso contrário (se estivermos vendo um arquivo people ), loop pelos nomes dos animais ( critter s) e conte as linhas que combinam com elas.
  • Ao atingir o END de todas as entradas, relatar os nomes dos animais que foram extraídos dos nomes dos arquivos animals , e as contagens de quantas vezes apareceram em um arquivo people .

Isso não pesquisará o diretório people recursivamente; Eu não vi nenhuma afirmação na pergunta que isso foi desejado.

    
por 26.04.2015 / 08:13
0

Acho que se você der os padrões como entrada para grep usando stdin , ele concatenará resultados para todos os padrões. Então, AFAIK, a única maneira de superar esse problema é chamar uma nova instância do grep para cada padrão.

Este script funcionaria neste caso

for animalName in $(ls -1 ~/animals | cut -d. -f1);
    do
        echo "$animalName: $(grep -R -h -c $animalName ~/people | paste -sd+ | bc)";
done

Isso está na linha do que você tentou com algumas pequenas alterações. Primeiro, a opção -h em grep suprime a impressão de nomes de arquivos. Segundo, com apenas grep , a saída para um padrão seria como

1
0
3
2

Queremos adicionar todos esses números. O comando paste une essas linhas com um + e, em seguida, passa a string formada para bc para calcular o resultado.

NOTA: Se seus nomes de animais contiverem novas linhas ou qualquer caractere especial (em alguma terra estranha), não é aconselhável analisar a saída de ls .

    
por 26.04.2015 / 07:56