Я работаю find . -type d
на довольно большом дереве каталогов. Я только интересуюсь нахождением каталогов в этом дереве, но когда я выполнил strace против процесса, чтобы удостовериться, что это делало то, что я ожидал, что это сделает, я заметил, что существует огромный объем операций, потраченных впустую, работая fstat против файлов в дереве.
newfstatat(AT_FDCWD, "file1", {st_mode=S_IFREG|0600, st_size=7690, ...}, AT_SYMLINK_NOFOLLOW) = 0
newfstatat(AT_FDCWD, "file2", {st_mode=S_IFREG|0600, st_size=7696, ...}, AT_SYMLINK_NOFOLLOW) = 0
newfstatat(AT_FDCWD, "file3", {st_mode=S_IFREG|0600, st_size=7687, ...}, AT_SYMLINK_NOFOLLOW) = 0
newfstatat(AT_FDCWD, "file4", {st_mode=S_IFREG|0600, st_size=10455, ...}, AT_SYMLINK_NOFOLLOW) = 0
Не знает находка, что inode указывает на каталог, пока это не выполняет fstat? Если это так, затем это собирается занять много времени. Некоторые из этих каталогов, вероятно, имеют миллионы объектов в них, но я действительно только забочусь о каталогах.
В конечном счете я хотел бы сообщение о dirsize и путь каждого из каталогов в моем дереве файла. Каков самый быстрый/больше всего эффективный способ для меня сделать это?
Да, похоже, что это действительно тот случай, когда find использует fstat для определения типа файла. Это немного удивительно, учитывая, что dirent содержит информацию, начиная с ядра 2.6.4.
Не все файловые системы поддерживают расширенное поведение dirent, поэтому либо это верно в вашем случае, либо find не использует Это. Мы не можем решить, не зная тип вашей файловой системы.
Я уверен, что вы знаете, что каталог - это особый тип файла в парадигме UNIX. Чтобы определить, является ли что-то каталогом или файлом другого типа, его нужно запросить, и fstat () - хороший способ сделать это.
Я считаю, что более поздние файловые системы и fs-драйверы хранят отдельную таблицу только для каталогов, но команда find существует несколько десятилетий назад и, вероятно, либо не адаптирована к новым файловым системам, либо поддерживает обратную совместимость.
Вы можете подделать это, запустив повторяющееся задание из CRON (с хорошим значением> 0, если вы хотите упростить использование ввода-вывода для других процессов), которое выполняет:
find ${DIRECTORY} -type d -print >${DIRECTORY}/.only_folders
Затем, когда вам это нужно, используйте содержимое предварительно созданного файла вместо повторного обхода каталога.
cat "${DIRECTORY}/.only_folders" |while read FOLDER ; do do_work.sh ${FOLDER} ; done
вместо чего-то вроде
find ${DIRECTORY} -type d |xargs do_work.sh