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 desafortunado, de sobrescrever 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 o glob for *
, o comando poderá ser reduzido para $(ls | wc -l)
. Analisar a saída de ls
sempre me deixa desconfortável, mas aqui deve funcionar, desde que seus nomes de arquivo não contenham novas linhas, ou seu ls
os escapa. E $(ls -d -- * 2>/dev/null | wc -l)
tem a vantagem de lidar com o caso de uma globalização não correspondente graciosamente (isto é, retorna 0 nesse caso, enquanto o método set *
requer testes complexos se a glob puder estar vazia).
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 para ls
pode falhar com um erro lista de argumentos muito longa se houver muitos arquivos correspondentes.