A primeira maneira de simplificar o script seria salvar o número de arquivos em uma variável, para que você não precise recalculá-la.
Outras maneiras de gerar o número de arquivos no diretório atual:
n=$(ls -l | grep -c ^-)
Aqui, a simplificação está usando a opção -c
do grep para contar as correspondências. Existe o risco de se confundir as correspondências quando analisar a saída de ls se houver um arquivo chamado $'some\n-file'
, que finge colocar um hífen no início da linha.
n=$(stat -c %F -- * | grep -c 'regular .*file')
O .*
no grep é responsável pelas correspondências "arquivo regular" e "arquivo vazio regular". O comando stat produz o tipo de cada arquivo, e o *
shell glob evita as preocupações com ls
.
Se você estiver familiarizado com o bash, mas já ouviu falar de zsh e sua poderosa sintaxe de globalização de nomes de arquivo , você poderia:
n=$(zsh -c 'a=( *(.) ); echo ${#a}')
Onde criamos uma matriz chamada a
, que é preenchida com a lista de arquivos *
, filtrada apenas por "arquivos simples" com .
.
Para imprimir o plural corretamente, considere uma declaração de caso:
case $n in
(1) printf "1 file";;
(*) printf "$n files";;
esac
Uma instrução case permitiria mais flexibilidade se você quisesse imprimir mensagens diferentes para diferentes números de arquivos, por exemplo: "No files!".
Mais simplesmente, considere uma condicional:
[[ $n == 1 ]] && printf "1 file" || printf "$n files"
Finalmente, contornar a sugestão da steeldriver:
n=$( files=(*); dirs=(*/); echo $(( ${#files[@]} - ${#dirs[@]} )))
printf "%d file%s" "$n" "$(test "$n" -ne 1 && echo s)"
Isso atribui um valor a n
(eventualmente) abrindo uma substituição de comando; dentro dessa substituição de comando temporária, eu crio duas matrizes: files
para tudo e dirs
para apenas diretórios. O último ato da substituição do comando é relatar a diferença entre os dois. O printf
, em seguida, imprime o número de arquivos junto com o sufixo plural apropriado.
Isso usa qualquer configuração que você tenha para dotglob
; se você quiser forçar a contagem (ou omissão) de arquivos de pontos, você deve definir ou desmarcar dotglob
dentro da substituição do comando:
use o valor atual de dotglob:
n=$( files=(*); dirs=(*/); echo $(( ${#files[@]} - ${#dirs[@]} )))
aplica a contagem de arquivos de pontos, independentemente do ponto atual:
n=$(shopt -s dotglob;
files=(*); dirs=(*/); echo $(( ${#files[@]} - ${#dirs[@]} )))
aplica não a contagem de arquivos de pontos, independentemente do ponto atual:
n=$(shopt -u dotglob;
files=(*); dirs=(*/); echo $(( ${#files[@]} - ${#dirs[@]} )))