Как получить количество файлов в папке в виде переменной?
Используя bash, как можно получить количество файлов в папке, исключая каталоги из оболочки script без запроса интерпретатора?
С помощью друга я пробовал
$files=$(find ../ -maxdepth 1 -type f | sort -n)
$num=$("ls -l" | "grep ^-" | "wc -l")
который возвращается из командной строки:
../1-prefix_blended_fused.jpg: No such file or directory
ls -l : command not found
grep ^-: command not found
wc -l: command not found
соответственно. Эти команды работают в командной строке, но НЕ с bash script.
Учитывая файл, заполненный файлами изображений, отформатированными как 1-pano.jpg
, я хочу захватить все изображения в каталоге, чтобы получить самый большой нумерованный файл для последующего обработки на следующем обработанном изображении.
Почему расхождение?
Ответы
Ответ 1
Кавычки вызывают сообщения об ошибках.
Чтобы узнать количество файлов в каталоге:
shopt -s nullglob
numfiles=(*)
numfiles=${#numfiles[@]}
который создает массив, а затем заменяет его количеством элементов. Это будет включать файлы и каталоги, но не точечные файлы или .
или ..
или другие точечные каталоги.
Используйте nullglob
, чтобы пустой каталог давал счет 0 вместо 1.
Вместо этого вы можете использовать find -type f
или подсчитать каталоги и вычесть:
# continuing from above
numdirs=(*/)
numdirs=${#numdirs[@]}
(( numfiles -= numdirs ))
Также см. "Как найти самый последний (самый новый, самый ранний, самый старый) файл в каталоге?"
Вы можете иметь столько пробелов, сколько хотите внутри блока исполнения. Они часто помогают в удобочитаемости. Единственным недостатком является то, что они делают файл немного больше и могут немного замедлить первоначальный анализ (только). Есть несколько мест, которые должны иметь пробелы (например, около [
, [[
, ]
, ]]
и =
в сравнениях), и несколько мест, которые не должны (например, около =
в назначении).
Ответ 2
ls -l | grep -v ^d | wc -l
Одна строка.
Ответ 3
Как насчет:
count=$(find .. -maxdepth 1 -type f|wc -l)
echo $count
let count=count+1 # Increase by one, for the next file number
echo $count
Обратите внимание, что это решение неэффективно: оно создает дочерние оболочки для команд find
и wc
, но оно должно работать.
Ответ 4
file_num=$(ls -1 --file-type | grep -v '/$' | wc -l)
это немного легче, чем команда find, и подсчитывает все файлы текущего каталога.
Ответ 5
Избавьтесь от котировок. Оболочка обрабатывает их как один файл, поэтому ищет "ls -l".
Ответ 6
Простой эффективный метод:
#!/bin/bash
RES=$(find ${SOURCE} -type f | wc -l)
Ответ 7
Самый простой и надежный способ, который я могу придумать, - использовать команду find
для создания надежно исчисляемого результата.
Подсчет количества выводимых символов find
с помощью wc
:
find . -maxdepth 1 -type f -printf '.' | wc --char
или длина строки вывода find
:
a=$(find . -maxdepth 1 -type f -printf '.')
echo ${#a}
или используя вывод find
для заполнения арифметического выражения:
echo $(($(find . -maxdepth 1 -type f -printf '+1')))
Ответ 8
Перемотайте qoutes, и вы будете в порядке
Ответ 9
Развернувшись на принятом ответе (Деннис W): когда я пробовал этот подход, у меня были неправильные подсчеты для dirs без subdirs в Bash 4.4.5.
Проблема заключается в том, что по умолчанию nullglob не установлен в Bash, а numdirs=(*/)
устанавливает массив 1 элемента с шаблоном glob */
. Аналогично, я подозреваю, что numfiles=(*)
будет иметь 1 элемент для пустой папки.
Настройка shopt -s nullglob
, чтобы отключить nullglobbing, разрешает проблему для меня. Для отличной дискуссии о том, почему nullglob по умолчанию не установлен на Bash, см. Ответ здесь: Почему nullglob не используется по умолчанию?
Примечание. Я бы прокомментировал ответ напрямую, но не имел точек репутации.
Ответ 10
Вот один из способов сделать это как функцию. Примечание: вы можете передать этот пример, dirs for (количество каталогов), файлы для подсчета файлов или "all" для подсчета всего в каталоге. Не пересекает дерево, поскольку мы не собираемся этого делать.
function get_counts_dir() {
# -- handle inputs (e.g. get_counts_dir "files" /path/to/folder)
[[ -z "${1,,}" ]] && type="files" || type="${1,,}"
[[ -z "${2,,}" ]] && dir="$(pwd)" || dir="${2,,}"
shopt -s nullglob
PWD=$(pwd)
cd ${dir}
numfiles=(*)
numfiles=${#numfiles[@]}
numdirs=(*/)
numdirs=${#numdirs[@]}
# -- handle input types files/dirs/or both
result=0
case "${type,,}" in
"files")
result=$((( numfiles -= numdirs )))
;;
"dirs")
result=${numdirs}
;;
*) # -- returns all files/dirs
result=${numfiles}
;;
esac
cd ${PWD}
shopt -u nullglob
# -- return result --
[[ -z ${result} ]] && echo 0 || echo ${result}
}
Примеры использования функции:
folder="/home"
get_counts_dir "files" "${folder}"
get_counts_dir "dirs" "${folder}"
get_counts_dir "both" "${folder}"
Напечатает что-то вроде:
2
4
6