Ao contar linhas com wc, não imprima um erro sempre que houver um diretório

12

Quero contar o número total de linhas em todos os /etcarquivos, mas não os arquivos nos subdiretórios, então digitei: wc -l /etc/* | tail -1e a saída é como:

xxxx is a directory 
yyyy is a directory
total 1752

Minha pergunta é: como posso remover (excluir) esses comentários e existe uma maneira melhor de fazer esse tipo de contagem?

Hamza
fonte
1
Eu acho que o uso de find não é 100% correto, porque em / etc não existem apenas arquivos regulares f, mas também links l. então esta versão é muito melhor: $ sudo wc -l / etc / * 2> / dev / null | tail -1
Hamza

Respostas:

14

Você pode enviar as mensagens de erro para / dev / null

$ wc -l /etc/* 2>/dev/null | tail -1

Com este comando, você está vendo apenas o número de linhas nos arquivos que são legíveis mundialmente. Para ver o número de linhas de todos os arquivos com os quais você teria que elevar o comando sudo.

$ sudo wc -l /etc/* 2>/dev/null | tail -1
LD James
fonte
8

Isolar arquivos e executar o wc neles

O que wc -l /etc/*faz é *expandir para todos os itens dentro do /etc/diretório. Assim, o objetivo é isolar arquivos e executar wcneles. Existem várias maneiras de fazer isso.

para loop com teste

O testcomando, ou abreviado com mais frequência, [pode ser usado para descobrir se um item é um arquivo comum como este:

[ -f "$FILE" ]

Portanto, o que podemos fazer é iterar sobre todos os itens /etc/e executá wc-los se e somente se o comando acima retornar verdadeiro. Igual a:

for i in /etc/*; do [ -f "$i" ] && wc -l "$i" ; done             

encontrar

Podemos também usar findcom -maxdepth, -typee -execbandeiras

find /etc/ -maxdepth 1 \( -type f -o -type l \) -exec wc -l {} +

  • -maxdepthinforma a profundidade da estrutura de diretórios; O valor 1 significa apenas os arquivos no diretório que queremos.
  • -type f diz para procurar arquivos regulares, OU (representado por -osinalizador) por links simbólicos (representados por type l). Toda essa bondade é colocada entre colchetes ()com escape, de \modo que o shell os interpreta como parte do findcomando, em vez de outra coisa.
  • -exec COMMAND {} +aqui a estrutura executa qualquer comando que dermos, +indicando pegar todos os arquivos encontrados e colocá-los como argumentos na linha de comando para o COMMAND.

Para produzir o total, poderíamos canalizar a produção da tailmesma forma

$ find /etc/ -maxdepth 1 \( -type f -o -type l \) -exec wc -l {} + | tail -n 1           
[sudo] password for xieerqi: 
 11196  total

Nota

É mais fácil usar apenas wc -l /etc/* 2>/dev/null | tail -1, como na resposta de LD James, no entanto, finddeve ser parte do hábito de lidar com arquivos para evitar o processamento de nomes de arquivos difíceis. Para mais informações, leia o ensaio Como lidar com nomes de arquivos corretamente

Sergiy Kolodyazhnyy
fonte
5

find faz isso facilmente:

sudo wc -l $(find /etc/ -maxdepth 1 -type f -iname '*')

Resultado:

...
828 /etc/mime.types
25 /etc/ts.conf
66 /etc/inputrc
 0 /etc/subgid-
8169 total

MAS se você quiser apenas o número como saída e nada mais:

sudo wc -l $(find /etc/ -maxdepth 1 -type f -iname '*') | grep total | awk '{print $1}'

EDIT : newlineserro kos disse prevalece. Somente o uso o -execretifica. Além disso, /etcnão contém esses arquivos.

Resultado:

8169

Conforme apontado por kos , o comando acima pode ser reduzido para:

sudo wc -l $(find /etc/ -maxdepth 1 -type f -iname '*') | awk 'END {print $1}'

EDIT : newlineserro kos disse prevalece. Somente o uso o -execretifica. Além disso, /etcnão contém esses arquivos.

Resultado:

8169
Rafael
fonte
4
Qual é o propósito -iname '*'? não findcorresponde a tudo por padrão?
Steeldiver
@steeldriver - Não funcionou para mim sem '*'.
Raphael
2

Usando z-shell ( zsh), a rainha das conchas , em vez de bash.

sudo wc -l /etc/*(.) | tail -1
AB
fonte