Existe uma alternativa mais sucinta ao piping para wc para contar arquivos em um diretório

12

Se eu fizer ls -1 target_dir | wc -l , receberei uma contagem de arquivos em um diretório. Eu acho isso um pouco complicado. Existe uma maneira mais elegante ou sucinta?

    
por codecowboy 01.05.2014 / 11:09

5 respostas

12

Assumindo o bash 4+ (que qualquer versão suportada do Ubuntu tem):

num_files() (
    shopt -s nullglob
    cd -P -- "${1-.}" || return
    set -- *
    echo "$#"
)

Chame como num_files [dir] . dir é opcional, caso contrário, ele usa o diretório atual. Sua versão original não conta com arquivos ocultos, então não faz isso. Se você quiser, shopt -s dotglob antes de set -- * .

Seu exemplo original conta não apenas com arquivos regulares, mas também diretórios e outros dispositivos - se você realmente quer apenas arquivos regulares (incluindo links simbólicos para arquivos regulares), você precisará checá-los:

num_files() (
    local count=0

    shopt -s nullglob
    cd -P -- "${1-.}" || return
    for file in *; do
        [[ -f $file ]] && let count++
    done
    echo "$count"
)

Se você tiver o GNU find, algo assim também é uma opção (note que isso inclui arquivos ocultos, o que seu comando original não fez):

num_files() {
    find "${1-.}" -maxdepth 1 -type f -printf x | wc -c
}

(altere -type para -xtype se você também quiser contar links simbólicos para arquivos regulares).

    
por 01.05.2014 / 11:18
3

f=(target_dir/*);echo ${#f[*]}

funciona corretamente para arquivos com espaços, novas linhas, etc. no nome.

    
por 01.05.2014 / 22:36
2

ls é multi-colunas apenas se for enviado diretamente para um terminal, você pode remover a opção "-1", você pode remover a opção wc "-l", apenas leia o primeiro valor (solução lenta , para não ser usado para evidências leguais, investigações criminais, missão crítica, operações táticas ..).

ls target | wc 
    
por 01.05.2014 / 11:17
2

Se for sucinto você (em vez de exatidão ao lidar com arquivos com novas linhas em seus nomes, etc.), eu recomendo apenas o aliasing wc -l to lc ("line count"):

$ alias lc='wc -l'
$ ls target_dir|lc

Como outros notaram, você não precisa da opção -1 para ls , pois é automática quando ls está gravando em um pipe. (A menos que você tenha ls aliado para sempre usar o modo de coluna. Eu já vi isso antes, mas não com muita frequência.)

Um lc alias é bastante útil em geral, e para essa pergunta, se você observar o caso "contar o diretório atual", ls|lc será o mais sucinto possível.

    
por 02.05.2014 / 17:49
2

Até agora Aaron é a única abordagem mais sucinta do que a sua. Uma versão mais correta da sua abordagem pode parecer:

ls -aR1q | grep -Ecv '^\./|/$|^$'

Que recursivamente lista todos os arquivos - não diretórios - um por linha, incluindo .dotfiles abaixo do diretório atual, usando shell globs, conforme necessário, para substituir os caracteres não imprimíveis. grep filtra qualquer lista de diretórios pai ou .. ou * / ou linhas em branco - então deve haver somente uma linha por arquivo - a contagem total de qual grep retorna para você. Se você quiser incluir diretórios filhos, faça o seguinte:

ls -aR1q | grep -Ecv '^\.{1,2}/|^$'

Remova o -R em ambos os casos, se você não quiser resultados recursivos.

    
por 19.06.2014 / 19:58