Если вы хотите подсчитать количество не -скрытых файлов с расширением .json
в текущем каталоге, вы должны сделать:
(){echo $#} *.json(NoN)
(N
для nullglob
, oN
для отключения сортировки, которая здесь нам не нужна ).
ls -l | grep.json | wc -l
неверно по ряду причин:
.
— это оператор регулярного выражения, который соответствует любому одиночному символу. Если вы хотите найти строку .json
, это будет grep -F.json
или grep '\.json'
или grep '[.]json'
. Xjson
ищется в каждой строке. С помощью ls -l
вы печатаете имя файла, имя пользователя, имя группы, цель символических ссылок, все из которых могут содержать Xjson
. /
(ссылки могут содержать/
); который включает новую строку. Итак, если у вас есть файл с именем xjson\nyjson
, который является символической ссылкой на ajson\nbjson
, без -q
, ls -l
для этого файла будет напечатано 3 строки, каждая из которых будет содержать Xjson
. Вы также можете получить сюрпризы, если некоторые имена файлов содержат последовательности байтов, которые не образуют допустимые символы в текущей локали. grep | wc -l
обычно можно заменить на grep -c
. ls -l *.json | wc -l
еще хуже. Помимо слишком длинного списка аргументов потенциальная проблема , уже отмеченная @L.ScottJohnson, есть также:
.json
файла, вы получите 0
, а также ошибку от zsh
, поскольку глобус *.json
не соответствует. ls -l
перечисляет их содержимое,поэтому, если у вас есть каталог dir.json
, все строки, полученные в результате его перечисления, будут подсчитаны. Как правило, вы хотите использовать -d
при передаче расширения глобуса в ls
. .json
начинается с -
, это будет принятоls
(в качестве опции, особенно реализациями GNU или busybox ls
, которые принимают опции даже после не -аргументов опции ). Большинство из них можно исправить с помощью чего-то вроде:
LC_ALL=C ls -qd -- *.json | wc -l
Но здесь вся работа выполняется оболочкой. Оболочка расширяет *.json
до списка соответствующих файлов и передает его в ls
. ls
используется там только для печати каждого в отдельной строке для передачи в wc
, чтобы он мог их подсчитать. ls
также выполняет много ненужной работы, например выполняет системный вызов stat()
для каждого, чтобы проверить его наличие (с -l
, он выполняет lstat()
и несколько uid/gid для разрешения имени пользователя/группы., и readlink()
s для символических ссылок )и снова сортирует список (оболочка уже сортирует расширение *.json
).
Оболочка вполне способна подсчитать это расширение сама по себе.
С (){echo $#} *.json(NoN)
мы используем анонимную функцию, вы также можете использовать временный массив:files=(*.json(NoN)); echo $#files
.
Также обратите внимание, что для построения этого списка нужно только прочитать содержимое текущего каталога, ему не нужно пытаться -искать каждый файл по отдельности, как это делает ls
.
Обратите внимание, что этот синтаксис специфичен для zsh
. Эквивалентом в POSIX sh
будет что-то вроде:
set -- [*].json *.json
case $1$2 in
('[*].json*.json') shift 2;;
(*) shift;;
esac
echo "$#"
(и список файлов находится в"$@"
(отсортированном )).