Isso é feito de maneira segura e portátil. Não vai ficar confuso com nomes estranhos de arquivos.
for f in *; do [ -d ./"$f" ] && find ./"$f" -maxdepth 1 -exec echo \; | wc -l && echo $f; done
Se você tem um conjunto específico de subdiretórios nos quais está interessado, é possível substituir o *
por eles.
Por que isso é seguro? (e, portanto, digno do script)
Nomes de arquivo podem conter qualquer caractere, exceto /
. Existem alguns caracteres que são tratados especialmente pelo shell ou pelos comandos. Esses incluem espaços, novas linhas e traços.
Usar a construção for f in *
é uma maneira segura de obter cada nome de arquivo, independentemente do conteúdo.
Depois de ter o nome do arquivo em uma variável, você ainda terá que evitar itens como find $f
. Se $f
continha o nome do arquivo -test
, find
reclamaria da opção que você acabou de fornecer. A maneira de evitar isso é usando ./
na frente do nome; Desta forma, tem o mesmo significado, mas não começa mais com um traço.
Novas linhas e espaços também são um problema. Se $f
contiver "Olá, amigo" como um nome de arquivo, find ./$f
, será find ./hello, buddy
. Você está dizendo find
para ver ./hello,
e buddy
. Se isso não existir, ele irá reclamar, e nunca irá aparecer em ./hello, buddy
. Isso é fácil de evitar - use aspas em torno de suas variáveis.
Por fim, os nomes de arquivos podem conter novas linhas, portanto, contar novas linhas em uma lista de nomes de arquivos não funcionará; você receberá uma contagem extra para cada nome de arquivo com uma nova linha. Para evitar isso, não conte as novas linhas em uma lista de arquivos; em vez disso, conte as novas linhas (ou qualquer outro caractere) que representem um único arquivo. É por isso que o comando find
tem simplesmente -exec echo \;
e não -exec echo {} \;
. Eu só quero imprimir uma única nova linha com a finalidade de contabilizar os arquivos.