Se você souber que o diretório atual contém pelo menos um arquivo não oculto:
set -- *; echo "$#"
Isso é obviamente generalizável para qualquer glob.
Em um script, isso tem o efeito colateral às vezes infeliz de substituir os parâmetros posicionais. Você pode contornar isso usando um subshell ou com uma função (versão Bourne / POSIX) como:
count_words () {
eval 'shift; '"$1"'=$#'
}
count_words number_of_files *
echo "There are $number_of_files non-dot files in the current directory"
Uma solução alternativa é $(ls -d -- * | wc -l)
. Se a glob estiver *
, o comando pode ser abreviado para $(ls | wc -l)
. Analisar a saída de ls
sempre me deixa desconfortável, mas aqui deve funcionar, desde que os nomes dos seus arquivos não contenham novas linhas ou que você os ls
escape. E $(ls -d -- * 2>/dev/null | wc -l)
tem a vantagem de lidar com o caso de um globo sem correspondência normalmente (ou seja, ele retorna 0 nesse caso, enquanto o set *
método exige testes minuciosos se o globo estiver vazio).
Se os nomes dos arquivos puderem conter caracteres de nova linha, uma alternativa é usar $(ls -d ./* | grep -c /)
.
Qualquer uma dessas soluções que dependem de passar a expansão de uma glob ls
pode falhar com um erro muito longo da lista de argumentos se houver muitos arquivos correspondentes.