Почему `ls -l` считает больше файлов, чем я?

Видимо я не могу сосчитать. Я думаю, что есть три файла в /media

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

Тем не мение, ls -l находит 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

И если я сделаю ls -la Я получаю только . а также .. в дополнение к вышесказанному, но количество total 20

Какое объяснение?

2 ответа

Решение

12 вы видите не количество файлов, а количество использованных дисковых блоков.

От 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.

Всего идет от 12 в 20 когда вы используете ls -la вместо ls -l потому что вы считаете две дополнительные директории: . а также .., Вы используете четыре дисковых блока для каждого (пустого) каталога, поэтому ваше общее количество увеличивается с 3 × 4 до 5 × 4. (По всей вероятности, вы используете один дисковый блок размером 4096 байт для каждого каталога; info страница указывает, что утилита не проверяет формат диска, но предполагает размер блока 1024 если не указано иное.)

Если вы хотите просто получить количество файлов, вы можете попробовать что-то вроде

ls | wc -l

Пользователь user4556274 уже ответил на вопрос " почему". Мой ответ служит только для предоставления дополнительной информации о том, как правильно считать файлы.

В сообществе Unix общее мнение состоит в том, что анализ выходных данных ls очень плохая идея, поскольку имена файлов могут содержать управляющие символы или скрытые символы. Например, из-за символа новой строки в имени файла мы имеем ls | wc -l скажите нам, что есть 5 строк в выводе ls (что у него есть), но на самом деле в каталоге всего 4 файла.

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

Способ № 1: найти утилиту

find Команда, которая обычно используется для работы с синтаксическим анализом имен файлов, может помочь нам, напечатав номер инода. Будь то каталог или файл, он имеет только один уникальный номер inode. Таким образом, используя -printf "%i\n" и исключая . с помощью -not -name "." мы можем иметь точное количество файлов. (Обратите внимание на использование -maxdepth 1 для предотвращения рекурсивного спуска в подкаталоги)

$> 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

Способ № 2: глобстар

Простой, быстрый и в основном портативный способ:

$ set -- * 
$ echo $#
228

set Команда используется для установки позиционных параметров оболочки ($<INTEGER> переменные, как в echo $1). Это часто используется для обхода /bin/sh ограничение отсутствия массивов. Версия, которая выполняет дополнительные проверки, может быть найдена в ответе Джилла на Unix&Linux.

В оболочках, которые поддерживают массивы, такие как bash, мы можем использовать

items=( dir/* )
echo ${#items[@]}

как предложено Steeldriver в комментариях.

Подобный трюк с find метод, который использовал wc и Globstar можно использовать с stat для подсчета номеров инодов в строке:

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

Альтернативный подход заключается в использовании подстановочного знака в for петля. (Обратите внимание, что в этом тесте используется другой каталог для проверки того, превращается ли этот подход в подкаталоги, чего нет - 16 - это проверенное количество элементов в моем ~/bin)

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

Метод № 3: другие языки / переводчики

Python также может иметь дело с проблемными именами файлов путем печати длины списка с учетом моего os.listdir() функция (которая не является рекурсивной и будет перечислять только элементы в каталоге, указанном в качестве аргумента).

$> python -c "import os ; print os.listdir('.')"                              
['file2.txt', 'file1.txt', 'FILE\nNAME', 'file3.txt']
$>  python -c "import os ; print(len(os.listdir('.')))"                    
4

Смотрите также

Другие вопросы по тегам