Como posso usar a palavra counter ( wc) e a canalização para contar quantos arquivos ou diretórios estão no /usr/bindiretório?
Como posso usar a palavra counter ( wc) e a canalização para contar quantos arquivos ou diretórios estão no /usr/bindiretório?
Respostas:
Uma abordagem seria usar lspara nos fornecer uma lista dos arquivos, mas queremos que essa lista mostre apenas 1 arquivo ou diretório por linha. A -1opção fará isso por nós.
$ ls -1
dir1
dir2
dir3
fileA
fileB
fileC
Crie os dados de amostra acima em um diretório vazio.
$ mkdir dir{1..3}
$ touch file{A..C}
Verifique-o:
$ ls
dir1 dir2 dir3 fileA fileB fileC
Agora, para contar, você pode usar wc -lpara contar o número de linhas, que correspondem a um arquivo ou diretório na ls -1saída.
$ ls -1 | wc -l
6
(observe, porém, que ele não inclui os arquivos ocultos)
Para contar arquivos ou diretórios, você precisa mudar um pouco sua tática. Nesse caso, eu usaria, ls -lpois mostra o que é um diretório e o que é um arquivo.
$ ls -l
total 12
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir1
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir2
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir3
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileA
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileB
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileC
Em seguida, podemos usar greppara filtrar diretórios ou não diretórios da seguinte forma:
# directories
$ ls -l | grep "^d"
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir1
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir2
drwxrwxr-x 2 saml saml 4096 Nov 16 09:48 dir3
# regular files
$ ls -l | grep "^-"
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileA
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileB
-rw-rw-r-- 1 saml saml 0 Nov 16 09:49 fileC
Agora basta usar wc -lnovamente para contar o acima:
# directories
$ ls -l | grep "^d" | wc -l
3
# regular files
$ ls -l | grep "^-" | wc -l
3
Porém, você pode evitar wccompletamente e usar grepa -copção:
$ ls -l | grep -c '^d'
(novamente, arquivos ocultos não estão incluídos. Observe que diretórios e regulares são dois tipos de arquivos. Existem muitos outros como pipes nomeados, links simbólicos, dispositivos, soquetes ...).
Se você precisar encontrar os arquivos e diretórios de forma recursiva /usr/bin, provavelmente desejará alterar completamente as táticas e usar outra ferramenta chamada find.
$ find /usr/bin | wc -l
4632
(embora acima de /usr/binsi esteja incluído na contagem)
As mesmas técnicas que usei acima podem ser empregadas lspara fazer algo semelhante, mas lsgeralmente não é uma boa ferramenta para analisar a saída. findpor outro lado, foi construído para isso e oferece opções para localizar arquivos ou diretórios.
# find files
$ find /usr/bin -type f
# find directories
$ find /usr/bin -type d
(observe que, desta vez, findestá incluindo arquivos ocultos (exceto .e ..)).
Eu nunca descobri por que um caractere de nova linha é um caractere legal a ser usado ao criar nomes de arquivo ou diretório. Portanto, os métodos discutidos acima usam wce lsnão os contendem, portanto, use-os com isso em mente.
Crie um diretório e nome de arquivo com novas linhas.
$ mkdir $'dir4\n5'
$ touch $'fileD\nE'
ls mostra-os corretamente:
$ ls -1
dir1
dir2
dir3
dir4?5
fileA
fileB
fileC
fileD?E
Mas wcconta os diretórios e arquivos que contêm novas linhas como 2 itens, não um.
$ ls -1 | wc -l
10
Um método para contornar isso, se usar a implementação GNU de, findé usar finda capacidade de imprimir outra coisa no lugar de cada arquivo que encontrar e depois contá-los.
$ find . -printf . | wc -c
9
Aqui estamos encontrando tudo no diretório atual (exceto ..) e imprimindo um ponto ( .) para cada um e, em seguida, contando os pontos usando wca capacidade de contar bytes em vez de linhas wc -c,.
/usr/binsejam todos bem formatados (e também não contenham espaços, portanto, tecnicamente, você poderia apenas echo * | wc -w), é importante notar que tudo isso ocorrerá nos nomes de arquivos que contêm novas linhas.
ls -lou ls -1quebre b / c, estamos contando linhas, não palavras! O findpode quebrar, mas, novamente, estamos contando linhas, não palavras.
touch $'foo\nbar'dentro de um diretório vazio seguido por um de seus comandos (digamos ls -1 | wc -l), serão relatados dois arquivos em vez de um - porque esse arquivo possui duas linhas no que diz wcrespeito. A menos que lssubstitua as novas linhas por algum outro personagem (acho que não, mas novamente não estou em posição de testar agora).
wc -cum problema ao contar os períodos?
Se você deseja obter uma divisão do número de cada tipo de arquivo recursivamente sob algum diretório, com o GNU find, você pode:
find /some/dir/. ! -name . -printf '%y\n' | sort | uniq -c | sed '
s/f/regular files/;t
s/d/directories/;t
s/l/symbolic links/;t
s/s/Unix domain sockets/;t
s/b/block devices/;t
s/c/character devices/;t
s/p/FIFOs/;t
s/D/Doors/;t
s/n/network special files/;t
s/.$/others (&)/'
No /usr/binmeu sistema, isso fornece:
3727 regular files
710 symbolic links
Ativado /dev:
83 block devices
203 character devices
31 directories
426 symbolic links
1 FIFOs
1 Unix domain sockets
Para links simbólicos, se você preferir contá-los como o tipo de arquivo ao qual eles apontam, em vez disso symbolic links, altere-o para:
find /some/dir/. ! -name . -printf '%Y\n' | sort | uniq -c | sed '
s/f/regular files/;t
s/d/directories/;t
s/N/broken symbolic links/;t
s/s/Unix domain sockets/;t
s/b/block devices/;t
s/c/character devices/;t
s/p/FIFOs/;t
s/D/Doors/;t
s/n/network special files/;t
s/.$/others (&)/'
O que agora dá para o meu /usr/bin:
1 directories
4434 regular files
2 broken symbolic links
(um link simbólico quebrado é um link simbólico para um arquivo para o qual findnão é possível determinar o tipo porque o arquivo não existe ou está em um diretório ao qual você não tem acesso ou há um loop na resolução do caminho do arquivo No meu caso, aqueles 2 onde links simbólicos para arquivos que agora se foram).
Nenhum deles conta .e ... Se você os quisesse incluídos (por que você desejaria?), Não há outra maneira findde assumir que eles estão lá para todos os diretórios e contá-los sistematicamente:
find /some/dir/. -printf '%y\n' \( -name . -printf 'd\n' -o \
-type d -printf 'd\nd\n' \) | sort | uniq -c | sed '
s/f/regular files/;t
s/d/directories/;t
s/l/symbolic links/;t
s/s/Unix domain sockets/;t
s/b/block devices/;t
s/c/character devices/;t
s/p/FIFOs/;t
s/D/Doors/;t
s/n/network special files/;t
s/.$/others (&)/'
Que então dá no meu /usr/bin:
2 directories
3727 regular files
710 symbolic links
Se você não tem acesso ao GNU find, pode reescrever o primeiro como:
find /some/dir/. ! -name . \( \
-type f -exec printf '%.0sregular files\n' {} + -o \
-type d -exec printf '%.0sdirectories\n' {} + -o \
-type l -exec printf '%.0ssymbolic links\n' {} + -o \
-type s -exec printf '%.0sUnix domain sockets\n' {} + -o \
-type b -exec printf '%.0sblock devices\n' {} + -o \
-type c -exec printf '%.0scharacter devices\n' {} + -o \
-type p -exec printf '%.0sFIFOs\n' {} + -o \
-exec printf '%.0sothers\n' {} + \) | sort | uniq -c
Agora, estritamente falando, não contamos arquivos, mas entradas de diretório . Um diretório como /usr/binnormalmente possui várias entradas que apontam para o mesmo arquivo. Por exemplo, aqui, eu tenho:
$ ls -lid /usr/bin/{nvi,nview,nex}
672252 -rwxr-xr-x 3 root root 434616 May 25 07:40 /usr/bin/nex
672252 -rwxr-xr-x 3 root root 434616 May 25 07:40 /usr/bin/nvi
672252 -rwxr-xr-x 3 root root 434616 May 25 07:40 /usr/bin/nview
Essas são 3 entradas de diretório (também conhecidas como nomes de arquivos ou links físicos) para o mesmo arquivo (aquele com o inode 672252. Para contar arquivos em vez de entradas de diretório e com GNU finde GNU uniq(ignorando .e ..arquivos que de qualquer forma são links físicos para outros diretórios):
find /some/dir/. ! -name . -printf '%y\t%D:%i\n' |
sort -u |
cut -f1 |
uniq -c |
sed '
s/f/regular files/;t
s/d/directories/;t
s/l/symbolic links/;t
s/s/Unix domain sockets/;t
s/b/block devices/;t
s/c/character devices/;t
s/p/FIFOs/;t
s/d/Doors/;t
s/n/network special files/;t
s/.$/others (&)/'
No meu /usr/bin, isso dá:
3711 regular files
710 symbolic links
Você não disse se deseja que todo o arquivo seja em / usr / bin recursivamente ou logo abaixo do primeiro nível. Além disso, como você vai conseguir as palavras que está contando? A maneira usual de descobrir é executar a busca no wc. Assim: find / usr / bin | wc -l Find listará tudo o que há lá, diretórios e arquivos. Wc -l contará todas as linhas na saída de localização. Isso é um trabalho de classe? Está tudo bem se estiver, mas eu queria saber por que você precisava dessas informações para que eu pudesse adaptar a resposta com mais cuidado. Entre em contato se precisar de mais. Costa
No bash, sem ferramentas externas.
cd dir/ || exit; shopt -s nullglob; shopt -s dotglob; count=(*); echo "${#count}"
No bash, sem ferramentas externas e recursão.
shopt -s globstar; shopt -s dotglob
for dir in **/*/; do
unset d f
for files in "$dir"*; do
[[ -f $files ]] && ((++f))
[[ -d $files ]] && ((++d))
done;
printf '%s\n' "$dir - files: ${f:-0} - directories: ${d:-0}"
done
.nem ..entradas. Você pode querer desambiguar arquivo x arquivo normal.