Como posso usar a palavra counter ( wc
) e a canalização para contar quantos arquivos ou diretórios estão no /usr/bin
diretório?
Como posso usar a palavra counter ( wc
) e a canalização para contar quantos arquivos ou diretórios estão no /usr/bin
diretório?
Respostas:
Uma abordagem seria usar ls
para nos fornecer uma lista dos arquivos, mas queremos que essa lista mostre apenas 1 arquivo ou diretório por linha. A -1
opçã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 -l
para contar o número de linhas, que correspondem a um arquivo ou diretório na ls -1
saí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 -l
pois 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 grep
para 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 -l
novamente 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 wc
completamente e usar grep
a -c
opçã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/bin
si esteja incluído na contagem)
As mesmas técnicas que usei acima podem ser empregadas ls
para fazer algo semelhante, mas ls
geralmente não é uma boa ferramenta para analisar a saída. find
por 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, find
está 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 wc
e ls
nã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 wc
conta 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 find
a 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 wc
a capacidade de contar bytes em vez de linhas wc -c
,.
/usr/bin
sejam 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 -l
ou ls -1
quebre b / c, estamos contando linhas, não palavras! O find
pode 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 wc
respeito. A menos que ls
substitua as novas linhas por algum outro personagem (acho que não, mas novamente não estou em posição de testar agora).
wc -c
um 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/bin
meu 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 find
nã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 find
de 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/bin
normalmente 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 find
e 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.