Por que o 'ls -l' conta mais arquivos que eu?

24

Aparentemente não posso contar. Eu acho que existem três arquivos em /media

$ tree /media
/media
├── foo
├── onex
└── zanna
3 directories, 0 files

No entanto, ls -l encontra 12.

$ ls -l /media
total 12
drwxr-xr-x  2 root root 4096 Jul 31 20:57 foo
drwxrwxr-x  2 root root 4096 Jun 26 06:36 onex
drwxr-x---+ 2 root root 4096 Aug  7 21:17 zanna

E, se eu fizer ls -la , receberei apenas . e .. além do acima, mas a contagem será total 20

Qual é a explicação?

    
por Zanna 10.08.2016 / 16:44

2 respostas

32

O 12 que você vê não é o número de arquivos, mas o número de blocos de disco consumidos.

De info coreutils 'ls invocation' :

 For each directory that is listed, preface the files with a line
 'total BLOCKS', where BLOCKS is the total disk allocation for all
 files in that directory.  The block size currently defaults to 1024
 bytes, but this can be overridden (*note Block size::).  The
 BLOCKS computed counts each hard link separately; this is arguably
 a deficiency.

O total passa de 12 para 20 quando você usa ls -la em vez de ls -l porque está contando dois diretórios adicionais: . e .. . Você está usando quatro blocos de disco para cada diretório (vazio), então seu total vai de 3 × 4 a 5 × 4. (Com toda a probabilidade, você está usando um bloco de disco de 4096 bytes para cada diretório como indica a página info , o utilitário não verifica o formato do disco, mas supõe um tamanho de bloco de 1024 , a menos que seja instruído de outra forma.

Se você quiser simplesmente obter o número de arquivos, tente algo como

ls | wc -l
    
por user4556274 10.08.2016 / 16:49
18

user4556274 já respondeu ao porquê . Minha resposta serve apenas para fornecer informações adicionais para como contar corretamente os arquivos.

Na comunidade Unix, o consenso geral é que analisar a saída de ls é uma idéia muito ruim, já que nomes de arquivos podem conter caracteres de controle ou caracteres ocultos. Por exemplo, devido a um caractere de nova linha em um nome de arquivo, temos ls | wc -l informando que há 5 linhas na saída de ls (o que ele possui), mas na realidade há apenas 4 arquivos no diretório.

$> touch  FILE$'\n'NAME                                                       
$> ls                                                                         
file1.txt  file2.txt  file3.txt  FILE?NAME
$> ls | wc -l
5

O comando find , que é normalmente usado para trabalhar com a análise de nomes de arquivos, pode nos ajudar aqui imprimindo o número do inode . Seja um diretório ou um arquivo, ele tem apenas um número inode exclusivo. Assim, usando -printf "%i\n" e excluindo . via -not -name "." , podemos ter uma contagem precisa dos arquivos. (Observe o uso de -maxdepth 1 para impedir a descida recursiva em subdiretórios)

$> find  -maxdepth 1 -not -name "." -print                                    
./file2.txt
./file1.txt
./FILE?NAME
./file3.txt
$> find  -maxdepth 1 -not -name "." -printf "%i\n" | wc -l                    
4

O mesmo truque pode ser usado com stat para contar os números de inode por linha:

$> LC_ALL=C stat ./* --printf "%i\n" | wc -l                                          
4

Uma abordagem alternativa é usar um curinga. (Observe que este teste usa um diretório diferente para testar se essa abordagem desce em subdiretórios, o que não acontece - 16 é o número verificado de itens no meu ~/bin )

$> count=0; for item in ~/bin/* ; do count=$(($count+1)) ; echo $count ; done | tail -n 1                                
16

O Python também pode lidar com nomes de arquivos problemáticos por meio da impressão do tamanho de uma lista, considerando minha função os.listdir() (que é não-recursiva e listará apenas itens no diretório fornecido como argumento).

$> python -c "import os ; print os.listdir('.')"                              
['file2.txt', 'file1.txt', 'FILE\nNAME', 'file3.txt']
$>  python -c "import os ; print(len(os.listdir('.')))"                    
4
    
por Sergiy Kolodyazhnyy 10.08.2016 / 22:51