Learning Platform
Глоссарий Troubleshooting
Урок 20.03 · 22 мин
Средний
ripgrepfdbatdustModern CLIRust tools

ripgrep, fd, bat: modern замены grep/find/cat

Классические Unix-tools (grep, find, cat, du) написаны в 1970-х. Они работают везде, но: grep не рекурсивен по умолчанию, find имеет нечитаемый синтаксис (find . -name '*.py' -exec grep -l TODO {} \;), cat не показывает синтаксис, du выводит мегабайты текста.

Modern Rust/Go replacements решают это: ripgrep (rg) — grep на стероидах с уважением .gitignore, fd — find с интуитивным синтаксисом и параллелизмом, bat — cat с подсветкой синтаксиса и line numbers, dust — du с визуальной иерархией.

В DE workflow эти tools экономят минуты на каждой задаче «поиск в коде / по логам / по конфигам». На большом monorepo разница grep -r (минуты) vs rg (секунды) меняет рабочий процесс.

В этом уроке: rg, fd, bat, dust — установка, основной синтаксис, DE use cases.


ripgrep (rg): grep на стероидах

grep -r работает, но: проходит по всем файлам включая .git, node_modules, build, требует явных include/exclude. ripgrep решает это автоматически.

Установка

# Debian/Ubuntu:
sudo apt install ripgrep

# macOS:
brew install ripgrep

# Команда называется rg:
rg --version

Дефолтное поведение

# rg рекурсивен по умолчанию:
rg ERROR

# Эквивалент grep:
grep -r ERROR .

# Но rg также:
# 1. Не лезет в .git/, node_modules/, target/, build/ (.gitignore)
# 2. Использует ВСЕ ядра CPU (parallel walking)
# 3. JIT regex engine — в разы быстрее
# 4. Подсвечивает matches в TTY
grep -r vs rg на real DE-репозитории
grep -rgrep -r PATTERN . — рекурсивный, single-threaded, читает ВСЁ включая node_modules
vs
rgrg PATTERN — parallel, respects .gitignore, JIT regex. На большом monorepo — секунды вместо минут
grep --includegrep -r --include='*.py' — включить только .py. Многословно
rg -t pyrg -t py PATTERN — поиск только в Python файлах. -t = type

Основные опции

# Поиск:
rg PATTERN
rg PATTERN /path/to/dir
rg PATTERN file.txt           # explicit file

# Тип файлов:
rg -t py "import pandas"      # только Python
rg -t yaml "image:"           # только YAML
rg -T js "broken"             # ИСКЛЮЧИТЬ JS

# Регистр:
rg -i ERROR                   # case-insensitive

# Word match:
rg -w ERROR                   # whole word (не ERRORS, не TRACEERROR)

# Fixed string (не regex):
rg -F "1.2.3"                 # точка как точка, не "любой символ"

# Context (как grep -A -B -C):
rg -C 3 ERROR                 # 3 строки до и после
rg -A 5 ERROR                 # 5 строк после

# Inverted:
rg -v INFO                    # строки БЕЗ "INFO"

# Только имена файлов:
rg -l ERROR                   # files-with-matches
rg --files-without-match TEST # files без матча

# Count:
rg -c ERROR                   # count matches per file

Регулярные выражения (Rust regex syntax)

rg 'log_\w+\('              # log_anything(
rg '^class\s+\w+'           # лидирующее class
rg 'TODO|FIXME|XXX'         # альтернация
rg '\d{4}-\d{2}-\d{2}'      # YYYY-MM-DD

# Не-greedy:
rg '<.*?>'                  # минимальный match

# PCRE2 features (-P):
rg -P '(?<=user_)\w+'       # lookbehind

ripgrep по умолчанию использует Rust regex engine — быстрый, но без lookbehind/lookahead. -P переключает на PCRE2 (как у Perl) — медленнее, но мощнее.

JSON output (—json)

rg --json ERROR /var/log/app.log
# Каждый match — JSON event со строкой, началом, концом match

Полезно для интеграции в Python/Node-скрипты — структурированный output легко парсится.

.rgignore

.gitignore — паттерны игнорирования файлов в Git

Как .gitignore, но для ripgrep specifically:

# .rgignore (в корне проекта):
*.log
generated/
private_data/

Полезно когда .gitignore слишком общий или нужны временные exclusions.


DE use case: поиск в логах

# Найти все ERROR за последний час в Airflow logs:
rg ERROR /var/log/airflow/ --max-count=100

# С контекстом (5 строк до):
rg -B 5 'Task failed' /var/log/airflow/dag_*.log

# Только error timestamps:
rg -o '^\S+ ERROR' /var/log/app.log | sort -u | wc -l

# Поиск конкретного query_id в DAG logs:
rg "query_id=abc-123" /var/log/airflow/

# По всем логам с конкретным DAG:
rg "DAG_ID=user_etl" /var/log/airflow/ -l   # только имена файлов

DE use case: поиск в Python codebase

# Найти все usage функции:
rg -tpy "from etl.utils import process_csv"
rg -tpy "process_csv\("

# Найти все sql queries:
rg -tpy "SELECT" --multiline
rg -tpy '"""[\s\S]*?SELECT[\s\S]*?"""' --multiline

# Найти все TODO:
rg -tpy 'TODO|FIXME' --no-heading | sort -k3 -t:

# Найти все hardcoded secrets (start с типичного pattern):
rg -tpy 'password\s*=\s*"' --json | jq 'select(.type=="match")'

fd: find rewrite

find синтаксис ужасен:

# find — найти все .py файлы, изменённые за день:
find . -type f -name '*.py' -mtime -1

# fd — то же самое:
fd -e py --changed-within 1d

Установка

# Debian (пакет называется fd-find на старых системах):
sudo apt install fd-find    # команда fdfind, можно alias fd=fdfind
sudo apt install fd          # на новых

# macOS:
brew install fd

Основные опции

# Поиск по pattern (regex по умолчанию):
fd 'config'                 # все файлы/директории с 'config' в имени
fd '\.py$'                  # точный regex

# Glob mode:
fd -g '*.py'                # как find -name

# Тип:
fd -t f config              # только files
fd -t d config              # только directories
fd -t l                     # symbolic links
fd -t x                     # executables

# Extension:
fd -e py                    # .py files
fd -e py -e pyi             # .py или .pyi

# Изменения по времени:
fd --changed-within 1d
fd --changed-before 1w

# Включить hidden:
fd -H config                # включая .config директории

# Включить gitignored:
fd -I                       # ignore .gitignore

# Execute:
fd -e py -x wc -l           # подсчитать строки в каждом .py
fd -e tmp -X rm             # удалить все .tmp файлы (-X = одна команда со всеми)
fd vs find
find . -namePOSIX, везде, но синтаксис громоздкий. -name требует кавычек, -exec — особый синтаксис
fd patternRust, в 5-10x быстрее на больших деревьях (parallel), respects .gitignore, простой синтаксис
-exec cmd \\;find -exec — по одному файлу на вызов. Медленно. -exec cmd + — все файлы одной командой
-x / -Xfd -x — параллельный exec для каждого файла. -X — одна команда со всеми файлами как args

Реальные DE use cases

# Найти все CSV больше 100MB:
fd -e csv -S +100M

# Удалить все .pyc файлы:
fd -e pyc -X rm

# Найти DAGs, изменённые за сутки:
fd -e py --changed-within 1d /opt/airflow/dags

# Конвертировать все .json в .jsonl через jq:
fd -e json -x sh -c 'jq -c ".[]" "{}" > "{.}.jsonl"'

bat: cat с подсветкой

cat показывает файл как plain text. bat — то же самое + syntax highlighting + line numbers + git diff indicators.

# Установка:
sudo apt install bat        # Debian/Ubuntu (команда batcat) или bat (новых)
brew install bat            # macOS

# Использование как cat:
bat config.yaml
bat /var/log/syslog
bat -p file.py              # plain mode (без line numbers/header)

# Несколько файлов:
bat *.py

# С line range:
bat -r 10:50 large_file.py  # строки 10-50
bat features
syntax highlight200+ языков. Python, YAML, JSON, SQL, Dockerfile — всё подсвечено. Можно настроить тему
line numbersПо умолчанию слева. Удобно ссылаться 'смотри строку 42'
git indicatorsВ git-репо bat показывает +/-/~/| для изменений vs HEAD
pager modeАвто-пейджинг через less если файл больше экрана. Можно отключить через --paging=never

bat для fzf preview

# В ~/.bashrc:
export FZF_DEFAULT_OPTS="--preview 'bat --color=always --style=numbers --line-range=:200 {}'"

Теперь каждый fzf preview подсвечен и красив.

bat как pager для man

export MANPAGER="sh -c 'col -bx | bat -l man -p'"
man find    # теперь подсвеченный man-page

dust: du с визуализацией

du -sh */ — текстовый вывод сортированный alphabetically. Найти “что занимает место” — pain.

dust показывает tree с прогресс-барами:

sudo apt install du-dust    # пакет называется du-dust
brew install dust

# Использование:
dust /var/log
# Output:
# 12G    /var/log
# ├─ 5G  apt
# ├─ 4G  journal
# │  ├─ 3G  user-1000
# │  └─ 1G  system
# ├─ 2G  airflow
# └─ 1G  syslog.1

Цветной tree с относительными размерами как ASCII-bar. Идеально для disk-space-investigation на production.

# Глубина:
dust -d 3 /var/log

# Сортировка:
dust -r          # reverse (smallest first)

# Только файлы:
dust -F /var/log

Дополнительные modern tools

entr — re-run on file change

sudo apt install entr
brew install entr

# Запустить тесты при изменении любого .py:
ls *.py | entr -r pytest

# Restart Python скрипт при изменении:
echo myscript.py | entr -r python myscript.py

# Lint скрипт при изменении:
ls *.sh | entr shellcheck /_

Hot-reload без специальных tools — для bash/SQL/manual scripts.

duf — df с UI

sudo apt install duf
brew install duf

duf
# Красивая таблица filesystems с usage bars, типами, mount points

procs — ps replacement

brew install procs
procs                    # цветная таблица процессов с tree view
procs node               # filter

sd — sed replacement

brew install sd

# sed:
sed -E 's/(\w+)@(\w+)\.com/\1 at \2/' file.txt

# sd:
sd '(\w+)@(\w+)\.com' '$1 at $2' file.txt

Более интуитивный синтаксис, поддерживает modern regex flavor.


Установка всех сразу

# Debian/Ubuntu:
sudo apt install ripgrep fd-find bat du-dust entr duf

# macOS:
brew install ripgrep fd bat dust entr duf procs sd

# Или одной командой через homebrew bundle:
cat > Brewfile <<EOF
brew "ripgrep"
brew "fd"
brew "bat"
brew "dust"
brew "entr"
brew "duf"
brew "procs"
brew "sd"
EOF
brew bundle

Когда использовать modern vs классику

modern vs classic — production context
Local devrg/fd/bat/dust — твоя машина, ты ставишь brew/apt. UX > совместимость
Production serversОбычные Ubuntu/Debian box. grep/find/cat — гарантированно есть. Не зависай на rg, если он не установлен
CI scriptsDocker images — можно добавить modern tools, особенно в alpine/debian. Часто и стоит — ускоряет билды
Airflow tasksWorker images — обычно minimal Python. modern tools обычно нет. Stick to grep/find/python для совместимости
TIP

В скриптах, которые деплоятся на production servers, не полагайся на rg/fd. Используй классический grep/find. Modern tools — для локальной продуктивности (поиск по логам через SSH с rg тоже работает, если ставить его на сервер). Знай оба, используй по контексту.


  • Урок 02 (fzf) — fzf использует find по умолчанию; переключи на fd через FZF_DEFAULT_COMMAND. bat для --preview.
  • Урок 04 (tmux) — modern tools полезны в panes.
  • Урок 05 (shell power) — zoxide, direnv, starship.
  • Модули 06-07 (text processing) — классические grep/sed/awk, основы.

Попробуй сам

  1. Установи rg, fd, bat:
# Linux:
sudo apt install ripgrep fd-find bat

# macOS:
brew install ripgrep fd bat
  1. Сравни скорости в проекте:
cd /your/large/project

time grep -r 'function' . > /dev/null
time rg 'function' > /dev/null
  1. Найди все Python с TODO:
rg -tpy 'TODO|FIXME' --no-heading | head -20
  1. Найди файлы изменённые за день:
fd --changed-within 1d -t f .
  1. Открой config с bat:
bat /etc/ssh/sshd_config
  1. Disk-space investigation:
dust ~
  1. Auto-run tests on save:
ls *.py | entr -r pytest
# Жми Ctrl-C для остановки

Проверка знанийKnowledge check
DE надо найти в monorepo (5000+ файлов, включая node_modules и .git) все Python-файлы, где упоминается функция `process_csv` с контекстом 5 строк, исключая тестовые файлы. Сравни классический подход с grep/find и modern с ripgrep.
ОтветAnswer
**Classic (grep + find)**:\nbash\nfind . -type f -name '*.py' -not -path '*/node_modules/*' -not -path '*/.git/*' -not -path '*test*' \\n | xargs grep -B 5 -A 5 'process_csv'\n\nПроблемы: 1) grep -r проходит по node_modules (миллионы файлов). 2) Ручной список exclude paths. 3) Single-threaded (медленно на больших деревьях). 4) Hardcoded test exclusion через path matching. **Modern (ripgrep)**:\nbash\nrg -tpy -C 5 'process_csv' --glob '!test_*.py' --glob '!*_test.py'\n\nПреимущества: 1) -tpy фильтрует только Python (без -name). 2) Дефолт respects .gitignore (node_modules/build/.git автоматически). 3) -C 5 = 5 строк до и после. 4) --glob '!pattern' — exclude tests чисто. 5) Parallel walking — в 5-10x быстрее. 6) Подсветка matches в TTY. На monorepo с 5000 файлов: grep ~10 секунд, rg ~0.5 секунды. Дополнительно: rg -tpy -C 5 'process_csv' --json даёт structured output для интеграции. fd для file finding: fd -e py -E '*test*' | xargs rg 'process_csv' — fd для filter, rg для grep. Combination — стандартный modern DE workflow.

Проверьте понимание

Результат: 0 из 0
Концептуальный
Вопрос 1 из 5. В чём принципиальное преимущество ripgrep (rg) над `grep -r` на современном DE-репозитории?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 5