advanced-workflows.md 7.8 KB

File Search Advanced Workflows

Advanced patterns combining fd, ripgrep (rg), and fzf for powerful file operations.

fd Advanced Patterns

Execution Patterns

# Execute command on each result
fd -e py -x wc -l {}                    # Line count per file
fd -e ts -x prettier --write {}         # Format each file
fd -e json -x jq '.name' {}             # Extract JSON field
fd -e md -x bat {}                      # Preview each with bat

# Parallel execution
fd -e ts -x -j4 tsc --noEmit {}         # 4 parallel type checks

# Batch mode (all files at once)
fd -e ts -X prettier --write            # Single prettier call
fd -e py -X wc -l                       # Single wc call

Pattern Matching

# Regex patterns
fd "^test_.*\.py$"                      # Files starting with test_
fd ".*\.(ts|tsx)$"                      # TypeScript files
fd "\d{4}-\d{2}-\d{2}"                  # Date in filename

# Glob patterns
fd -g "*.test.ts"                       # Glob mode
fd -g "config.{json,yaml,toml}"         # Multiple extensions

# Case sensitivity
fd -s "README"                          # Case-sensitive
fd -i "readme"                          # Case-insensitive (default)

Time-based Filtering

# Modified within time range
fd --changed-within 1h                  # Last hour
fd --changed-within 1d                  # Last day
fd --changed-before 1w                  # Older than 1 week

# Combine with other filters
fd -e py --changed-within 1d            # Python files modified today

Size Filtering

# Filter by size
fd --size +1m                           # Larger than 1MB
fd --size -100k                         # Smaller than 100KB
fd -e log --size +10m                   # Large log files

# Find empty files
fd --type f --size 0                    # Empty files
fd --type d --type empty                # Empty directories

ripgrep Advanced Patterns

Multiline Matching

# Match across lines
rg -U "class.*\n.*def __init__"         # Class with __init__
rg -U "import.*\n.*from"                # Consecutive imports

# Dotall mode (. matches newline)
rg -U "(?s)""".*?""""                   # Python docstrings

Replacement Preview

# Preview replacements without applying
rg "old_function" -r "new_function"     # Shows what would change
rg "v1" -r "v2" -n                      # With line numbers

# Apply with sd
sd "old_function" "new_function" $(rg -l "old_function")

Stats and Counts

# Statistics
rg --stats "TODO"                       # Match stats
rg -c "TODO"                            # Count per file
rg -c "TODO" | sort -t: -k2 -rn         # Sort by count

# File-level info
rg -l "pattern"                         # Files with matches
rg -L "pattern"                         # Files without matches
rg --files-without-match "pattern"      # Explicit no-match

Context Control

# Show context
rg -C 3 "error"                         # 3 lines before/after
rg -B 5 "def main"                      # 5 lines before
rg -A 10 "BEGIN"                        # 10 lines after

# Context separator
rg -C 2 --context-separator="---" "fn"  # Custom separator

fzf Power Workflows

Preview Commands

# File preview with bat
fd | fzf --preview 'bat --color=always --style=numbers --line-range :500 {}'

# Directory preview with eza
fd -t d | fzf --preview 'eza --tree --level=2 --color=always {}'

# Git status preview
git status -s | fzf --preview 'git diff --color=always {2}'

# Search result preview
rg -l "pattern" | fzf --preview 'rg -C 3 --color=always "pattern" {}'

Key Bindings

# Select and action
fd | fzf --bind 'enter:become(vim {})'
fd | fzf --bind 'ctrl-o:execute(code {})'
fd | fzf --bind 'ctrl-y:execute-silent(pbcopy < {})'

# Multiple bindings
fd | fzf \
  --bind 'enter:become(vim {})' \
  --bind 'ctrl-v:execute(code {})' \
  --bind 'ctrl-p:toggle-preview'

Multi-select Operations

# Select multiple files
fd | fzf -m | xargs rm -i               # Delete selected
fd -e ts | fzf -m | xargs code          # Open selected in VS Code

# With confirmation
fd -t f | fzf -m --header "Select files to delete" | \
  xargs -p rm

# Process each selection
fd -e py | fzf -m | while read f; do
  echo "Processing: $f"
  python "$f" --check
done

Combined Workflows

Code Investigation

# Find function definition
rg -n "def $FUNC" | fzf --preview 'bat {1} -H {2}'

# Find and open at line
rg -n "pattern" | fzf | awk -F: '{print "+" $2, $1}' | xargs nvim

# Interactive grep with live reload
fd -e py | fzf --ansi \
  --preview 'rg --color=always "pattern" {} || cat {}' \
  --bind 'change:reload(rg -l {} src/)'

Batch Operations

# Rename files matching pattern
fd "old" | while read f; do
  new="${f//old/new}"
  mv "$f" "$new"
done

# Find and convert
fd -e csv -x csvtojson {} > {.}.json

# Find, filter, act
fd -e ts | rg -l "deprecated" | fzf -m | xargs rm

Git Integration

# Changed files
git diff --name-only | fzf --preview 'git diff --color=always {}'

# Stage files interactively
git status -s | fzf -m | awk '{print $2}' | xargs git add

# Checkout branch
git branch | fzf | xargs git checkout

# Cherry-pick commits
git log --oneline | fzf | awk '{print $1}' | xargs git cherry-pick

# Interactive rebase
git log --oneline | fzf -m | tail -1 | awk '{print $1}' | xargs git rebase -i

Project Analysis

# Find TODO/FIXME with stats
rg -c "TODO|FIXME" | sort -t: -k2 -rn | head -10

# Large files in project
fd -t f -x du -b {} | sort -rn | head -20 | \
  awk '{printf "%.2f MB %s\n", $1/1048576, $2}'

# Files by extension
fd -t f | sed 's/.*\.//' | sort | uniq -c | sort -rn

# Dead code detection (imports not used)
rg "^import (\w+)" -o -r '$1' | sort -u > imports.txt
for imp in $(cat imports.txt); do
  count=$(rg "\b$imp\b" | wc -l)
  if [ "$count" -lt 2 ]; then
    echo "Possibly unused: $imp"
  fi
done

Shell Integration

Bash/Zsh Functions

# Interactive cd with preview
fcd() {
  local dir
  dir=$(fd -t d | fzf --preview 'eza --tree --level=2 {}') && cd "$dir"
}

# Find and edit
fe() {
  local file
  file=$(fd -t f | fzf --preview 'bat --color=always {}') && ${EDITOR:-vim} "$file"
}

# Search and edit at line
fge() {
  local result
  result=$(rg -n "" | fzf --preview 'bat {1} -H {2}')
  if [[ -n "$result" ]]; then
    local file=$(echo "$result" | cut -d: -f1)
    local line=$(echo "$result" | cut -d: -f2)
    ${EDITOR:-vim} "+$line" "$file"
  fi
}

# Git add with preview
fga() {
  git status -s | fzf -m --preview 'git diff --color=always {2}' | \
    awk '{print $2}' | xargs git add
}

Environment Variables

# fzf defaults
export FZF_DEFAULT_COMMAND='fd --type f --hidden --follow --exclude .git'
export FZF_DEFAULT_OPTS='
  --height 40% --layout=reverse --border
  --preview-window=right:60%
  --bind ctrl-/:toggle-preview
'

# Ctrl+T for file finder
export FZF_CTRL_T_COMMAND='fd --type f'
export FZF_CTRL_T_OPTS='--preview "bat --color=always {}"'

# Alt+C for directory finder
export FZF_ALT_C_COMMAND='fd --type d'
export FZF_ALT_C_OPTS='--preview "eza --tree --level=2 {}"'

Performance Optimization

Technique Example Speedup
Narrow path rg pattern src/ 2-10x
Use types rg -t py pattern 1.5-3x
Fixed strings rg -F "[literal]" 1.2-2x
Limit depth fd -d 3 pattern Variable
Ignore more fd -E "*.log" -E "tmp/" Variable
Parallel fd -x -j8 command 2-8x

Tips

  1. Use .ignore files - Create project-specific ignore rules
  2. Combine tools - fd for finding, rg for searching, fzf for selecting
  3. Preview everything - Use --preview to verify before acting
  4. Bind common actions - Set up fzf key bindings for frequent operations
  5. Shell functions - Create aliases for common workflows