6

Я хочу найти всех пользователей, показанных в каталоге /home/ чье потребление диска превышает 500 МБ. Следующая команда работает как положено.

cd /home/ && du */ -hs
68K     ajay/
902M    john/
250M    websites/

Из приведенного выше примера, только 902M john/ должны быть возвращены.

Как я могу заставить команду find выводить те же результаты?

4 ответа4

4

Не уверен, почему вы хотите что-то вроде find , поэтому вот скриптлет, который выполняет то, что вы спрашиваете в bash (но не работает как find):

max_size=$((500*1024))
cd /home/ && du -ks */ | while read size user ; do
  if [ $size -gt $max_size ] ; then
    echo "${user%/} exceeds quota"
  fi
done

Пример: (с меньшим размером):

$ du -sk */
2948    a/
4       a b/
640     b/
48      qt/

$ du -ks */ | while read size user ; do if [ $size -gt 600 ] ; then echo "${user%/} exceeds quota" ; fi ; done
a exceeds quota
b exceeds quota

${user%/} просто удаляет косую черту для дополнительной привлекательности.

0

Вы не можете сделать это только с помощью find, потому что find работает с отдельными файлами и не имеет концепции добавления размеров файлов. Вы можете перенаправить вывод find в другой инструмент, но зачем беспокоиться, когда du выполняет большую часть работы?

du -sm */ | sort -k1,1n | awk '$1 > 500 { sub(/$/, "M", $1); print $0 }'

Тест awk становится беспорядочным, когда во входные данные включается суффикс "читабельный человеком", потому что вам нужно убрать конечную букву "M", чтобы сделать целочисленное сравнение. Для вывода лично я бы пропустил суффикс "М", но это то, что было запрошено.

0

Это напечатает использование диска (в килобайтах) для файлов каждого пользователя в dir независимо от того, где находятся эти файлы:

find dir -printf "%u %b\n" | perl -n -e '@l = split; $sum{$l[0]} += $l[1]; END { foreach(sort(keys(%sum))) { print "$_ ",$sum{$_}/2," KiB\n"; }}'

Команда find печатает владельца и количество блоков для каждого файла и каталога в dir . Команда perl добавляет использование в хеш-ключ с именем пользователя, таким образом формируя сумму размеров файлов каждого пользователя; и затем содержимое хеша распечатывается.

0

Выложить как ответ.

Я использовал du-dms для получения согласованного вывода, который может быть обработан awk без дополнительного вмешательства. Вы правы, что удобочитаемый вывод лучше, поэтому окончательный вывод обрабатывается еще раз для этого.

#!/bin/bash

######################################################################
#  AUTHOR: Joe Negron - LOGIC Wizards ~ NYC
#  LICENSE: BuyMe-a-Drinkware: Dual BSD or GPL (pick one)
#  USAGE: byteMe (bytes)
#  ABSTRACT: Converts a numeric parameter to a human readable format.
#  URL: http://www.logicwizards.net/2010/10/19/byteme-a-simple-binary-metrics-bash-script-howto-convert-bytes-into-kb-mb-gb-etc-using-bash-bc/
######################################################################
function byteMe() { # Divides by 2^10 until < 1024 and then append metric suffix
declare -a METRIC=('B' 'KB' 'MB' 'GB' 'TB' 'XB' 'PB') # Array of suffixes
MAGNITUDE=0  # magnitude of 2^10
PRECISION="scale=1" # change this numeric value to inrease decimal precision
UNITS=`echo $1 | tr -d ','`  # numeric arg val (in bytes) to be converted
while [ ${UNITS/.*} -ge 1024 ] # compares integers (b/c no floats in bash)
  do
   UNITS=`echo "$PRECISION; $UNITS/1024" | bc` # floating point math via `bc`
   ((MAGNITUDE++)) # increments counter for array pointer
  done
echo -n "$UNITS${METRIC[$MAGNITUDE]}"
}

cd /home/ && du */ -bs | awk '$1 > 500 { print $0 }' | while read LINE; do
    SIZE=$(echo "$LINE" | cut -f 1)
    HRSIZE=$(byteMe "$SIZE")
    DIR=$(echo "$LINE" | cut -f 2)
    printf "%8s %s\n" "$HRSIZE" "$DIR"
done

Заметки:

  1. Функция gash была найдена поиском в Google (см. комментарии)
  2. Я изменил du -ms на du -bs, что позволило использовать функцию преобразования, которая принимает байты.
  3. Ограничение в 500 МБ все еще жестко закодировано. Не стесняйтесь изменять скрипт, чтобы принять его в качестве аргумента.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .