По-видимому, я не могу рассчитать. Я думаю, что существует три файла в /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
Каково объяснение?
The 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
говорят нам, что в выводе ls
есть 5 строк (которые у него есть), но на самом деле в каталоге только 4 файла.
$> touch FILE$'\n'NAME
$> ls
file1.txt file2.txt file3.txt FILE?NAME
$> ls | wc -l
5
Команда 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
Простой, быстрый и в основном портативный способ:
$ set -- *
$ echo $#
228
set
используется для установки позиционных параметров оболочки ( переменные $
, как в echo $1
). Это часто используется для работы вокруг /bin/sh
ограничения недостающих массивов. Версию, которая выполняет дополнительные проверки, можно найти в ответе Gille на Unix&Linux.
В оболочках, которые поддерживают массивы, такие как bash
, мы можем использовать
items=( dir/* )
echo ${#items[@]}
, как предлагает steeldriver в комментариях .
Аналогично методу find
, который использовал wc
и globstar, можно использовать с stat
для подсчета номеров кодов на строку:
$> LC_ALL=C stat ./* --printf "%i\n" | wc -l
4
Альтернативным подходом является использование спецсимвола в для петли
. (Обратите внимание, этот тест использует другой каталог для проверки, не попадает ли этот подход в подкаталоги, чего он не делает - 16 - это проверенное количество элементов в моем ~/bin
)
$> count=0; for item in ~/bin/* ; do count=$(($count+1)) ; echo $count ; done | tail -n 1
16
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