Существует несколько вещей неправильно здесь. Во-первых, Вы работаете /bin/sh
когда Вы на самом деле хотите работать /bin/bash
.
Теперь, часть Вашего сценария, который проверяет на скрытые файлы,
elif [[ -f $file && "$file" == ^. ]]; then
Если Вы запускаете свой скрипт как foo.sh /home/foo
, каждый $file
начнется /home/foo
таким образом, даже скрытые файлы не начнутся с точек. Кроме того, Вы не можете использовать ^
с ==
, это соответствует началу так или иначе (см. здесь).
Так или иначе рабочая реализация Вашего сценария была бы
#!/usr/bin/env bash
shopt -s dotglob
directoryCounter=0
fileCounter=0
hiddenDirectoryCounter=0
hiddenFileCounter=0
listAllFiles()
{
local dir=$1
local file
local bn="$(basename -- "$dir")"
for file in "$dir"/*; do
## Use ..* so you don't count the current dir (.) as hidden
if [[ $bn == .?* ]]; then
let hiddenDirectoryCounter+=1
listAllFiles "$file"
## Match only the filename, not the whole path
elif [[ -f $file && "$(basename "$file")" == .* ]]; then
let hiddenFileCounter+=1
elif [[ -f "$file" ]];then
let fileCounter+=1
elif [[ -d "$file" ]]; then
listAllFiles "$file"
let directoryCounter+=1
fi
done
}
listAllFiles $1
echo File found: $fileCounter
echo Directories found: $directoryCounter
echo Hidden directories found: $hiddenDirectoryCounter
echo Hidden files found: $hiddenFileCounter
Однако это не очень хороший способ сделать его, Вы не можете иметь дело больше чем с одним каталогом, как введено, что еще более важно, Вы только проверяете если $bn
скрытый каталог, никогда $file
что означает, что Вы никогда не будете находить больше чем один скрытый каталог, и Вы делаете его излишне сложным. Вы могли значительно упростить при помощи globstar
. Я записал бы это как так:
#!/usr/bin/env bash
shopt -s dotglob
## globstar causes ** to match all files and directories
## recursively.
shopt -s globstar
for dir in "$@"; do
for file in "$dir"/**; do
if [[ -f $file && "$(basename "$file")" == .* ]]; then
let hiddenFileCounter+=1
elif [[ -d $file && "$(basename "$file")" == .?* ]]; then
let hiddenDirectoryCounter+=1
elif [[ -f $file ]] ; then
let fileCounter+=1
elif [[ -d $file ]] ; then
let directoryCounter+=1
fi
done
done
echo Files found: $fileCounter
echo Directories found: $directoryCounter
echo Hidden directories found: $hiddenDirectoryCounter
echo Hidden files found: $hiddenFileCounter
Может дать представление о том, как долго система была занята, в секундах. Умножая это на 100, вы получаете сантисекунды - такова ваша цель?
IMO было бы более разумно рассмотреть, сколько процессорных секунд в общей сложности было доступно, и вычесть время простоя из этого:
Метрикой использования может быть:
Например,
, если бы система работала 10 секунд на 4-х ядрах с 5-ю секундами idle_time:
87.5% использования.
Или:
То же самое, сохраняет операцию.
Есть ли лучший способ получить загрузку процессора в качестве счетчика?
Я сделал это в системной диагностике C++ библиотеки, разобрав первую строку [1130576]/proc/stat[1130577], которая является совокупным итогом для всех ядер. Первые три поля - пользовательское время, низкоприоритетное (т.е. приятное) время и системное время. Общее это количество активного времени (обратите внимание, что единица измерения здесь не секунды, см. [1130578]/proc/stat[1130579] в разделе [1130580]man proc[1130581]).
Если вы проводите опрос в течение 5 секунд, предполагая, что USER_HZ равна 100, где [1130582]total_a[1130583] равна первый пример (user + nice + sys) и [1130584]total_b[1130585] является вторым:
Если вы умножите его на 100, у вас будет процент, указывающий на среднее значение за 5-секундный интервал.
Вот логика:
total_b - total_a[1130862] = активное время между выборками
Разделенное на продолжительность выборки, 5 секунд.
Разделенное на единицы в секунду измерения (USER_HZ)
Разделенное на количество ядер
USER_HZ - это почти наверняка 100. Проверить:
Скомпилировать: [1130594]gcc whatever.c[1130595], запустите [1130596]./a.out[1130597].
Также, если вы хотите, чтобы ваши результаты составляли общий процент использования, то вы должны снова разделить на время работы: