LINUX.ORG.RU

bfs 4.0.7

 , , , ,


0

2

15 июня состоялся выпуск 4.0.7 многопоточной консольной утилиты поиска файлов bfs (Breadth-First Search, поиск в ширину), написанной на языке C и распространяемой по лицензии BSD.

Изменения:

  • Для выбора количества используемых потоков теперь используется CPU affinity (sched_getaffinity(...) или xsysconf(_SC_NPROCESSORS_ONLN)).
  • -execdir /bin/... теперь разрешён даже при относительном пути в $PATH.
  • Тесты больше не зависят от утилиты expect.
  • Для соответствия GNU find теперь только последний аргумент -files0-from имеет эффект.
  • Исправлена ошибка -execdir {}, случайно добавленная в bfs 4.0.

>>> Подробности на GitHub

★★★★★

Проверено: Zhbert ()

А в чем киллер-фитча? Работает быстрее find? По возможностям поиска не уступает find? А поиск по содержимому умеет? Ну например мне надо найти файлы за определенный период времени и среди них файлы с определенным текстом.

Kolins ★★★★★
()
Последнее исправление: Kolins (всего исправлений: 2)
Ответ на: комментарий от Kolins

А в чем киллер-фитча?

В поиске в ширину. :)
Ещё может быть собрана с liburing и с Oniguruma для поддержки нескольких диалектов регэкспов.

Работает быстрее find?

Год назад измерял: fd 10.0.0 и bfs 3.2 (комментарий).

@CrX тоже где-то сравнивал, поищи.

А поиск по содержимому умеет?

Нет.

dataman ★★★★★
() автор топика
Последнее исправление: dataman (всего исправлений: 1)
Ответ на: комментарий от dataman

Год назад измерял: fd 10.0.0 и bfs 3.2 (комментарий).

Я может чего-то не понял, но из таблицы выходит что find быстрее или нет?

А поиск по содержимому умеет?

Нет.

жаль, по почтовому архиву шариться было-бы интересно с поиском внутри сразу

Kolins ★★★★★
()
Ответ на: комментарий от Kolins

но из таблицы выходит что find быстрее или нет?

У меня получилось так. Но был и другой результат: fd 10.0.0 и bfs 3.2 (комментарий)

жаль, по почтовому архиву шариться было-бы интересно с поиском внутри сразу

В ugrep 7.3 есть ugrep-indexer. Как раз для такого случая, наверное.

dataman ★★★★★
() автор топика
Последнее исправление: dataman (всего исправлений: 1)
Ответ на: комментарий от Kolins

Ну например мне надо найти файлы за определенный период времени и среди них файлы с определенным текстом.

Для этого нет необходимости в сторонних утилитах.

du -at |awk '$1 >= 1749980093 {print $2}' |grep -l hullygully $(cat)
kaldeon
()
Последнее исправление: kaldeon (всего исправлений: 4)
Ответ на: комментарий от dataman

В ugrep 7.3 есть ugrep-indexer.

Кстати, недавно увидел https://github.com/davidesantangelo/krep:

Fast text search tool with advanced algorithms, SIMD acceleration, multi-threading, and regex support. Designed for rapid, large-scale pattern matching with memory-mapped I/O and hardware optimizations.

Key Features

  • Multiple search algorithms: Boyer-Moore-Horspool, KMP, Aho-Corasick for optimal performance across different pattern types
  • SIMD acceleration: Uses SSE4.2, AVX2, or NEON instructions when available for blazing-fast searches
  • Memory-mapped I/O: Maximizes throughput when processing large files
  • Multi-threaded search: Automatically parallelizes searches across available CPU cores
  • Regex support: POSIX Extended Regular Expression searching
  • Multiple pattern search: Efficiently search for multiple patterns simultaneously
  • Recursive directory search: Skip binary files and common non-code directories
  • Colored output: Highlights matches for better readability
  • Specialized algorithms: Optimized handling for single-character and short patterns
  • Match Limiting: Stop searching a file after a specific number of matching lines are found.

Налетайте. :)

dataman ★★★★★
() автор топика

Ставил, воодушевившись описаниями. Но со временем, понял, что рука автоматически тянется к старому find или fd, когда лень писать каталог и -name.

Chiffchaff
()
Ответ на: комментарий от Chiffchaff

когда лень писать каталог и -name.

Я для этого наделал скрипты-(одно|пяти)строчники, типа bfsn:

bfs -nohidden -name "$@"

Или surm:

if [ "$1" ]; then
    sudo bfs -status -rm "$@"
else
    echo "Parameters are empty!"
fi

Да, я не использую алиасы. :)

dataman ★★★★★
() автор топика
Ответ на: комментарий от dataman

Я использую fish, и autoload функции вместо алиасов. Допустим, из недавно написанного:

function ,rt --description 'Позволяет выбрать и запустить тесткейс'
    set -l selection (rg -g 'test_*' -o -P '(?<=class )\w+TestCase' | fzf --ansi)
    if test $status -gt 0
        echo "Тест не был выбран"
        return
    end
    set -l module_name (echo $selection | rg -o -P --color=never '(?<=apps/)[^.]+' | sed 's|/|.|g')
    set -l class_name (echo $selection | rg -o -P --color=never '(?<=:).+')

    set -x OPTS "-k $module_name.$class_name"
    set -l command "OPTS='-k $module_name.$class_name' make autotests"
    history append $command
    make autotests
end

Позволяет быстро по нескольким символам найти в текущем проекте тесткейс, и запустить его, при этом команда для запуска добавляется в историю fish, чтобы легко было повторить запуск несколько раз подряд (чаще всего правишь код, запускаешь тест, повторяешь сначала).

Но с fd даже алиасы и функции не нужны: у него и так короткие запоминающиеся опции: -I - не использовать .gitignore, -H - искать среди скрытых файлов и каталогов. Думаю, что рано или поздно окончательно уйду с find на fd.

P.S. По чьему-то совету, называю все личные алиасы и функции с символа ,, чтобы проще было находить их в истории и по автодополнению.

Chiffchaff
()
Последнее исправление: Chiffchaff (всего исправлений: 2)
Ответ на: комментарий от Chiffchaff

Я использую fish

Я тоже использовал, но после переписывания fish на Rust в mc перестали работать курсорные клавиши. :)
У меня wezterm с протоколом kitty, к слову.

dataman ★★★★★
() автор топика
Ответ на: комментарий от dataman

Я тоже использовал, но после переписывания fish на Rust в mc перестали работать курсорные клавиши. :)

В смысле перестали? Работает - сейчас проверил в Konsole / Alacritty.

Ja-Ja-Hey-Ho ★★★★★
()
Ответ на: комментарий от Ja-Ja-Hey-Ho

Наверное, что-то из этого уже исправили.
Но мне уже неинтересно, я перешёл на Clifm 1.24.

dataman ★★★★★
() автор топика

Чтение с диска в много потоков - сомнительная затея. На ссд прироста не даст, на хдд наоборот убьёт скорость ещё больше. Разве что для tmpfs или когда всё в кеше полезно.

firkax ★★★★★
()
Ответ на: комментарий от firkax

Чтение с диска в много потоков - сомнительная затея

Подозреваю, что тут главная фишка не в чтении, а в параллельном выполнении -exec

annulen ★★★★★
()
Ответ на: комментарий от firkax

На ссд прироста не даст

С чего такая уверенность? На практике bfs показывает неплохой прирост по скорости на nvme.

iron ★★★★★
()

[bfs]

Это название соответствующего алгоритма поиска вершин графа. Как и зачем он используется в поиске файлов? ФС представляется в виде графа, а вершины файлы?

Ygor ★★★★★
()
Последнее исправление: Ygor (всего исправлений: 1)
Ответ на: комментарий от Ygor

Структура ФС же древовидная? А дерево — связный ациклический граф?
Хотя и не каждое дерево является графом.
Буратино, например, не был.

dataman ★★★★★
() автор топика
Ответ на: комментарий от Ygor

А если это написано на С, у ней там внутре своя реализация стёка?

Там trie и интрузивный список.

А потоки как мутятся?

#include <pthread.h>

dataman ★★★★★
() автор топика

два вопроса:
0. что, блин, такое "поиск в ширину"? сколько лет пользуюсь компами, а только сегодня узнал, что у файлов, оказывается, есть... ширина!
1. какой мудак додумался назвать свою программулину, как файловую систему? ну правда, "bfs" ассоциируется с чем угодно, но не с поиском файлов
пока писал, возник третий:
2. кто вообще пользуется всеми этими "убийцами" grep, ls и т.п.? базовые утилиты (coreutils, util-linux & co) есть буквально везде, работают одинаково, их поведение предсказуемо и не меняется десятилетиями. а эти все "улучшенные" мокрописьки есть только у васяна на локалхосте, а потом этот васян бееее-меееее - не помнит, как обычными grep/sed/find/etc пользоваться. ну и нафига оно надо?

PerdunJamesBond
()
Ответ на: комментарий от PerdunJamesBond
  1. https://en.wikipedia.org/wiki/Breadth-first_search. Например, у тебя есть такой каталог:
$ tree
.
├── b
│   ├── b1.txt
│   ├── b2.txt
│   └── b3.txt
├── c
│   ├── c1.txt
│   ├── c2.txt
│   └── c3.txt
└── d
    ├── d1.txt
    ├── d2.txt
    ├── d3.txt
    └── e
        ├── e1.txt
        └── e2.txt

Так работает find:

$ find
.
./c
./c/c1.txt
./c/c3.txt
./c/c2.txt
./d
./d/e
./d/e/e1.txt
./d/e/e2.txt
./d/d1.txt
./d/d2.txt
./d/d3.txt
./b
./b/b1.txt
./b/b3.txt
./b/b2.txt

А так bfs:

$ bfs
.
./c
./d
./b
./c/c1.txt
./c/c3.txt
./c/c2.txt
./d/e
./d/d1.txt
./d/d2.txt
./d/d3.txt
./b/b1.txt
./b/b3.txt
./b/b2.txt
./d/e/e2.txt
./d/e/e1.txt

То есть find сразу спускается максимально глубоко, a bfs сначала выдаёт все файлы с уровнем вложенности 0, потом 1, потом 2, и т.д.

  1. У человека, изучавшего алгоритмы в школе/универе, сразу ассоциируется с поиском в ширину
  2. Удобно, если нужно найти файл, который ты точно знаешь, что он не лежит глубоко. find может потратить кучу времени, обходя какой-нибудь гигантский каталог с огромным уровнем вложенности типа build каталога Yocto Linux
anatole
()
Последнее исправление: anatole (всего исправлений: 1)
Ответ на: комментарий от dataman

4300 строк сишной лапши в едином файле. Мммммм!…

wandrien ★★★
()

для поиска по содержимому использую mc т.к. в его панели результата удобно сразу переходить на каждый файл и даже на каждую строку в нем

но иногда mc не быстр в поиске, какая то есть более быстрая альтернатива для такого случая ?

x905 ★★★★★
()
Ответ на: комментарий от mx__

Это не совсем то. fzf позволяет быстро что-то найти в уже подготовленном списке строк. А чтобы его подготовить, надо сначала вызвать что-то типа find, fd или bfs, или даже ls. Например:

# fe [FUZZY PATTERN] - Open the selected file with the default editor
#   - Bypass fuzzy finder if there's only one match (--select-1)
#   - Exit if there's no match (--exit-0)
function ,fe --description "Open the selected file with the default editor"
    set files (fd -t f -H | fzf --query=$argv --multi --select-1 --exit-0 --preview="bat --color=always {}" | string split \n)

    if test -n "$files"
        nvim $files; and true # This line is added to prevent failure when using "set -e" in shell.
    end
end
Chiffchaff
()
Последнее исправление: Chiffchaff (всего исправлений: 1)
Ответ на: комментарий от x905

но иногда mc не быстр в поиске, какая то есть более быстрая альтернатива для такого случая

Я использую комбинации из ripgrep + fzf в командной строке.

Но т.к. чаще всего мне это нужно в neovim, то всё делаю там, через telescope, под капотом использующий те же ripgrep и fzf.

Chiffchaff
()
Ответ на: комментарий от Chiffchaff

вряд ли он юзает сторонние индексы, он скорее сам их делает. И потом хз как сейчас а раньше индексы стоили специальные проги про крону.

mx__ ★★★★★
()
Ответ на: комментарий от mx__

Я и не говорю, что использует. Не использует. Наверное, можно использовать индексы, но мне без необходимости - даже на самых больших проектах, с которыми работал, на SSD всё работает моментально даже без индексов.

Chiffchaff
()

То есть find сразу спускается максимально глубоко, a bfs сначала выдаёт все файлы с уровнем вложенности 0, потом 1, потом 2, и т.д.

спасибо, понял! а find нельзя так научить? у него ж там хренова куча всяких опций.

У человека, изучавшего алгоритмы в школе/универе, сразу ассоциируется с поиском в ширину

тут русский язык-то в школе учили единицы, а ты какие-то алгоритмы требуешь!

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

вот оно для чего! понятно.

PerdunJamesBond
()
Ответ на: комментарий от mx__

Ага, у меня такая функция есть:

function ,cdf
    set dir (fd -t d --search-path ~ | fzf --query=$argv --preview="tree -L 1 {}" --bind=space:toggle-preview --preview-window=:hidden)

    if test -n "$dir"
        cd $dir
    end
end

(честно стырено откуда-то).

По пробелу открывает превью каталога.

Chiffchaff
()
Ответ на: комментарий от Chiffchaff

Я видел подобные примеры, мне не нравится что нужно несколько поисковиков юзать. То примеры с fd, то c find - а зачем так я и не понял.

mx__ ★★★★★
()
Ответ на: комментарий от PerdunJamesBond

а find нельзя так научить? у него ж там хренова куча всяких опций.

У find есть -mindepth и -maxdepth для выбора диапазона глубины, но насколько я знаю, поменять алгоритм обхода на BFS у него нельзя

anatole
()
Ответ на: комментарий от mx__

Можно и с find сделать. Я просто делал попытки перейти на fd, и теперь в половине случаев использую одно, в половине - другое.

То же самое с grep и ripgrep. Где-то одно использую, где-то другое.

Тем более, что на работе полно старых систем, где нет ни того, ни другого.

Chiffchaff
()
Ответ на: комментарий от Chiffchaff

Тем более, что на работе полно старых систем, где нет ни того, ни другого.

Да ладно. Я понимаю всякие новомодные FZF, fd, ripgrep, но уж find и grep это утилиты классика, они уже лет 30 как во всех дистрах есть.

mx__ ★★★★★
()
Ответ на: комментарий от mx__

Я имею в виду, что новых утилит нет (rigpgrep, fd), возможно, поэтому я до конца ещё не перешёл на них во всех своих скриптах и привычках.

Можно всё установить себе в домашний каталог на каждом рабочем сервере, но что-то всё никак не дойдут руки.

Chiffchaff
()

написанной на языке C

Фу, как этим пользоваться? Нужно срочно переписать на расте

kas501 ★★★★
()
Ответ на: комментарий от PerdunJamesBond

На самому деле Корутилс и Баш-дрисня – ужасно неудобны. Они смогли выиграть у cmd.exe, но разве это достижение?

thegoldone ★★
()

А зачем это надо? Я обычным find то пользуюсь раз в сезон, зачем может понадобиться find с обходом в ширину

rk-d
()
Ответ на: комментарий от PerdunJamesBond

базовые утилиты (coreutils, util-linux & co) есть буквально везде, работают одинаково, их поведение предсказуемо и не меняется десятилетиями

Базовые утилиты задуманы (и даже написаны) в 70-80-х годах прошлого века, с соответствующей эргономикой.

Например, зачем у find всегда задавать каталог, с которого искать, если в 99.9% случаев это будет .? Зачем всегда писать длинный аргумент -name, если он будет там всегда с вероятностью 85-90%?

Зачем мне пользоваться grep, если я ищу, например, по исходному коду своего проекта. И grep будет искать мне:

  1. По бэкапам редакторов и утилит, типа *~, *.swp, и *.orig
  2. По файлам в каталоге .git
  3. По логам, и прочим артефактам разработки

Это всё банально очень неудобно. Новые утилиты пишутся с учётом понимания, накопленного за 30-40 лет, какие способы использования являются наиболее частыми.

Chiffchaff
()
Ответ на: комментарий от Chiffchaff

Это да, но конкретно bfs написали с максимальным сохранением CLI совместимости с find, со всей его эргономикой

anatole
()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.