Posso determinar o número de subdiretórios em um diretório usando `ls -l`?


8

Ao exibir diretórios usando ls -l, o número de links (o segundo campo na saída) é pelo menos dois: um para o nome do diretório e outro para.

$ mkdir foo
$ ls -l
total 2
drwxr-xr-x  2 user   wheel  512  4 oct 14:02 foo

É seguro assumir sempre que o número de links acima de 2 corresponde ao número de subdiretórios nesse diretório ( ..links)?

Respostas:


7

É geralmente verdadeiro em sistemas UNIX que o número de links para um diretório é o número de subdiretórios mais 2. No entanto, existem casos em que isso não é verdade:

  • Alguns departamentos permitem links físicos para diretórios. Depois, haverá mais de 2 links que não correspondem aos subdiretórios.

  • Existem sistemas de arquivos nos quais os diretórios não possuem entradas para .e ... O manual de localização do GNU menciona alguns exemplos na discussão de sua -noleafopção (que desativa uma otimização que supõe isso .e ..existe em todos os diretórios): “sistemas de arquivos em CD-ROM ou MS-DOS ou pontos de montagem de volume do AFS”

Uma maneira quase confiável de contar o número de subdiretórios (ainda pode falhar se um nome de arquivo contiver um caractere de nova linha) é

$(($(LC_ALL=C ls -la /path/to/directory | grep '^d' | wc -l) - 2)

Uma maneira mais confiável usa globs de shell */e .*/; como de costume, lidar com o caso em que o padrão não corresponde é um pouco trabalhoso (exceto no bash e no zsh, onde você pode ativar a nullglobopção).


2

Aqui está outra maneira de contar subdiretórios (não recursivamente) no Bash:

(
shopt -s nullglob dotglob
printf '%s\000' */ | tr -dc '\0' | wc -c  # wc counts null bytes
)

Como cada nome de arquivo está sendo finalizado por um caractere ASCII NUL, isso deve funcionar corretamente, mesmo que um nome de arquivo contenha um caractere de nova linha.



1

Não consigo encontrar nada na documentação que confirme que o número de links sempre será +2 no número de subdiretórios.

Mas, para encontrar a quantidade correta, use:

find . -type d -mindepth 1  -maxdepth 1 | wc -l

Ou, se você precisar usar ls -l, consulte a outra resposta.


Eu acho que você quis dizer -type d, mas: 1. isso requer o GNU find; 2. Você precisa subtrair 1 para o diretório inicial (ou passar -mindepth 1).
Gilles 'SO- stop be evil'

0

Não use lspara isso . Aqui está uma maneira que funciona com todos os nomes de arquivos, mesmo aqueles que contêm novas linhas, porque imprime apenas um caractere de nova linha em vez do nome do arquivo:

find . -mindepth 1 -maxdepth 1 -type d -printf '\n' | wc -l

Editar: a versão atual não resulta em nenhum aviso, porque -mindepthe -maxdepthdeve ser anterior -type(a árvore de diretórios é removida antes de procurar por diretórios, para economizar tempo).

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.