Такие факторы, как PLT
косвенность или syscall()'s
вариативность -ness (регистры должны быть сохранены в памяти )должны играть небольшую роль, учитывая, что getdents
является одним из самых дорогих вызовов в Linux.
Полное чтение пустого каталога на моей машине занимает около 5 мкс, каталога из 100 -элементов — 37 мкс, каталога из 1000 -элементов — 340 мкс, а каталога из 10 000 -элементов — 3,79 мс.
Что fdopendir
+ readdir
делает поверх getdents
, так это добавляет выделение/освобождение буфера (0,1 мкс )и stat
проверку того, что предоставленный fd относится к разновидности каталога (0,4 мкс ). readdir
затем делает один дешевый вызов для каждой записи каталога (перемещает позицию в буфере и, возможно, перезаполняет ).
Таким образом, есть что-то вроде одного -временного накладного расхода в 0,5 мкс, что составляет 10% времени сканирования каталога для пустых каталогов, но только 1% для каталогов из 100 -элементов и ничтожно мало для больших каталогов. Эти накладные расходы в 5 раз меньше (только стоимости выделения/освобождения ), если вам не нужен fdopen.(вам нужен fdopen только в том случае, если вы не можете diropen
напрямую и, следовательно, должны использовать отдельно полученный (например, openat
'ted )файловый дескриптор ).
Таким образом, если вы используете собственный -выделенный по времени буфер вместе с getdents
, вы можете сэкономить 2 -10% на стоимости сканирования пустых каталогов и ничтожно мало на больших те.
Что касается вызовов readdir
, стоимость косвенного обращения PLT на современном оборудовании обычно составляет менее 1 нс, служебные затраты на вызов функции составляют около 1 -2 нс. Учитывая, что время сканирования каталога составляет порядка микросекунд, вам нужно будет сделать не менее 1000 readdir
вызовов, чтобы эти коэффициенты были переведены в одну мкс, но тогда стоимость сканирования составляет 340 мкс, а накопленная 1 дополнительная мкс равна примерно 0,3% от этого --незначительного эффекта. Встраивание этихreaddir
(таким образом устраняет накладные расходы на вызовы и накладные расходы PLT )только для расширения кода, но это не сильно улучшит производительность, поскольку getdents
является здесь очень узким местом.
(readdir_r
дороже из-за дополнительной блокировки, но вам не нужно readdir_r
, потому что обычные вызовы readdir
обычно являются потокобезопасными -, если только у вас нет нескольких потоков, вызывающих их на ] тот же поток каталога . POSIX, возможно, еще не говорит об этом явно, но я считаю, что эта гарантия должна быть стандартизирована в ближайшее время, учитывая, что glibc зашел так далеко, что объявил readdir_r
устаревшим.)
[
... ]
проверяет строковые или числовые выражения. Если вы хотите увидеть, соответствует ли команда find
, вам нужно проверить, предоставила ли она какой-либо вывод (непустую строку -, протестированную с помощью-n
).
if [[ -n "$(find -name 'out.txt')" ]]
then
echo "out.txt found in $folder"
fi
Обратите внимание, что я использую современный синтаксис $(...)
для захвата вывода команды вместо устаревших обратных кавычек `...`
.
Другие комментарии,
Вы можете упростить njobs=
wc ${joblist} | awk '{print $1}' ``с njobs=$(wc -l <"$joblist")
, чтобы получить только количество строк.
Передать $i
в awk
как переменную,folder=$(awk -v i="$i" 'NR==i {print}' "$joblist}")
Не cd
во вложенную папку, а затем полагаться на использование cd
, чтобы вернуться туда, где вы были. Либо используйте относительные пути для ссылки на подкаталог, либо используйте подоболочку, чтобы сохранить cd
в ограниченном контексте. Здесь я использую первый подход
echo "$folder"
if [[ -n "$(find "$folder" -name 'out.txt')" ]]
then
echo "out.txt found in $folder"
fi
Если $folder
всегда является относительным путем, то ссылайтесь на него везде, где он используется как путь, как "./$folder". Это защищает от того, чтобы он начинался с тире (-
), что может сбить с толку команды, которые могут попытаться интерпретировать его как ряд опций.
В оболочке bash
уже есть переменная для текущего рабочего каталога, поэтому вы можете упростить cwd=`pwd`
доcwd="$PWD"
Используйтеhttps://shellcheck.net/для проверки кода. (Или установите его локально, если вы не хотите делиться личным кодом.)
#!/bin/bash
joblist='job_list.txt'
njobs=`wc ${joblist} | awk '{print $1}'`
cwd=`pwd`
while IFS= read -r line
do
folder="$line" #`awk '(NR=='${i}'){print}' ${joblist}`
echo $folder
cd ${folder}
if [ -f out.txt ]
then
echo out.txt found in $folder
fi
cd ${cwd}
done < job_list.txt
Надеюсь, это помогло. Немного проще... line=current-line-from'job_list.txt'
Он читает строку -за -строку, поэтому файл выглядит так:
folder1
folder2
folder234
мой вывод:
france1@macubuntu:/tmp/tmdf$ bash script.sh
folder1
folder2
folder234
out.txt found in folder234
france1@macubuntu:/tmp/tmdf$
надеюсь помог...