O resultado de “ls | wc -l ”não corresponde ao número real de arquivos [duplicado]

3

Eu preciso contar o número de arquivos em uma pasta e usar o seguinte comando.

cd testfolder
bash-4.1$ ls | wc -l
6

Na verdade, existem apenas cinco arquivos nessa pasta,

bash-4.1$ ls
total 44
-rw-r--r-- 1 comp 11595 Sep  4 22:51 30.xls.txt
-rw-r--r-- 1 comp 14492 Sep  4 22:51 A.pdf.txt
-rw-r--r-- 1 comp  8160 Sep  4 22:51 comparison.docx.txt
-rw-r--r-- 1 comp   903 Sep  4 22:51 Survey.pdf.txt
-rw-r--r-- 1 comp  1206 Sep  4 22:51 Steam Table.xls.txt

Parece que o ls | wc -l conta o total 44 como um arquivo, o que não está correto.

    
por user288609 05.09.2016 / 05:59

5 respostas

8

wc é um contador de caracteres, palavra e linha, não um contador de arquivos.

Você, o programador / roteirista, é responsável por fazer com que conte o que deseja e por ajustar o cálculo adequadamente.

No seu caso, você poderia fazer algo como:

echo $(('ls|wc -l'-1))

Por fim, note que o ls é provavelmente um alias, pois fornece uma listagem longa que não é a% normalls sem argumentos. Portanto, pode ser uma boa idéia se referir ao caminho completo de ls (geralmente /bin/ls ) para evitar confusão.

    
por 05.09.2016 / 06:08
11

Apenas uma informação extra para o acima,

Você deve usar find em vez de ls , se quiser processar a saída, tem alguns futuros que são mais adequados (por exemplo, -print0 ) para canalizar o resultado para outras aplicações.

No caso acima, você pode usá-lo assim,

find . -type f | wc -l

que listará quaisquer arquivos no diretório atual.

    
por 05.09.2016 / 08:32
9

Não está funcionando porque wc -l retorna o número de linhas da saída do comando ls , que nesse caso inclui total 44 . Como seu shell tem um alias para ls as ls -cml , você está obtendo essas informações extras que estão atrapalhando sua saída.

Em vez disso, use o comando "ls" -Aq | wc -l . O comando -A lista todos os arquivos no diretório, incluindo dotfiles, mas exclui . e .. . As citações aqui são importantes - elas ignoram o alias e executam /bin/ls diretamente.

-q garante que os nomes de arquivos sejam todos impressos em uma linha, mesmo que contenham caracteres de nova linha (que seriam então renderizados como ? ).

    
por 05.09.2016 / 06:27
1

Como outros já mencionaram, fazer ls | wc -l nem sempre é uma maneira confiável de obter arquivos em um diretório.

Aqui estão algumas maneiras confiáveis:

  • Você pode obter find para imprimir . para cada arquivo encontrado e obter wc -l para contar o número de linhas:

     find . -type f -printf '.\n' | wc -l
    
  • Se não houver muitos arquivos no diretório, você poderá salvar os nomes dos arquivos em uma matriz e, em seguida, obter o tamanho da matriz:

     for f in *; do [ -f "$f" ] && files+=("$f"); done && echo "${#files[@]}"
    

    Para todos os arquivos e diretórios, isso fica mais fácil:

     files=( * ) && echo "${#files[@]}"
    

Exemplo:

$ touch $'foo\nbar' 'foo bar' spam                         

$ ls | wc -l                      
4

$ find . -type f | wc -l                                   
4

$ find . -type f -printf '.\n' | wc -l
3

$ for f in *; do [ -f "$f" ] && files+=("$f"); done

$ echo "${#files[@]}"
3
    
por 05.09.2016 / 09:49
0
bash-4.1$ ls
1. total 44
2. -rw-r--r-- 1 comp 11595 Sep  4 22:51 30.xls.txt
3. -rw-r--r-- 1 comp 14492 Sep  4 22:51 A.pdf.txt
4. -rw-r--r-- 1 comp  8160 Sep  4 22:51 comparison.docx.txt
5. -rw-r--r-- 1 comp   903 Sep  4 22:51 Survey.pdf.txt
6. -rw-r--r-- 1 comp  1206 Sep  4 22:51 Steam Table.xls.txt

Está correto, existem 6 linhas na saída. Talvez você queira usar: ls -1 , que corresponde ao formato de coluna única e é assim:

ls -1
Desktop
Documents
Downloads
Music
Pictures
Public
Templates
Videos

Agora, wc -l retorna o número correto de arquivos:

ls -1 | wc -l
8
    
por 05.09.2016 / 16:29