Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

bashumerate

License: MIT GitHub release Tests

A programmable iterator for bash — enumerate files, lines, ranges, and lists, then pipe or exec commands on each item.

bashumerate demo

Install

# basher
basher install wallach-game/bashumerate

# manual
git clone https://github.com/wallach-game/bashumerate.git
ln -s "$PWD/bashumerate/bin/enumerate" ~/.local/bin/

Usage

enumerate -f <glob>...   -- <command>
enumerate -l <file>      -- <command>
enumerate -r <start> <end> -- <command>
enumerate -L <item>...   -- <command>

Examples

# List files
enumerate -f '*.sh'

# Count lines per file
enumerate -f '*.sh' -- 'wc -l {}'

# Iterate over lines from stdin
cat urls.txt | enumerate -l - -- 'curl -s {}'

# Numeric range
enumerate -r 1 10 -- 'printf "%02d\n" {}'

# Pipe to xargs
enumerate -f '*.log' | xargs rm

# Filter results
enumerate --include '*.md' --exclude 'README*' -f .

The {} placeholder is replaced with each item.
Use -- to separate source args from the command.

Sources

Flag Source Args Description
-f, --files files glob... Enumerate files matching glob pattern(s)
-l, --lines lines file or - Enumerate lines from a file or stdin
-r, --range range start end Enumerate integers from start to end
-L, --list list item... Enumerate literal items

Other options

Flag Description
--include <glob> Only include items matching glob
--exclude <glob> Exclude items matching glob
-0, --null NUL-delimited input/output
-n, --dry-run Print commands without executing them
-p, --parallel Execute commands in parallel
-P, --max-procs N Limit parallel jobs (default: number of CPUs)
-s, --speed Speed mode — inline execution, skip filters/dry-run/parallel
-q, --quiet Suppress error messages
--help Show help

Adding a source

Drop a file in lib/enumerators/foo.sh containing enumerate_source_foo():

# lib/enumerators/docker.sh
enumerate_source_docker() {
  docker ps --format '{{.Names}}' | while read -r name; do
    printf '%s\0' "$name"
  done
}
enumerate docker -- 'docker restart {}'

Performance

enumerate is significantly faster than xargs -I{} and find -exec for per-item command execution, thanks to streaming (no temp file I/O), eval-based execution (no subprocess per item), and an optimized inlined speed mode (-s).

Benchmark results on AMD Ryzen 9 5900X (24 cores):

Test Items xargs -I{} enumerate enumerate -s vs xargs
echo per item 1000 710ms 59ms 26ms 12-27x
echo per item 10000 6.07s 484ms 12.5x
file listing 10000 7.16s 623ms 11.5x
wc per item 10000 comparable for loop w/ ext cmd is 11x slower

For synthetic no-op benchmarks (:), enumerate -s is ~17x slower than a bare for loop (down from ~1500x before optimizations). For any real command (echo, wc, curl, etc.), the overhead is negligible — the command's own execution time dominates.

Run your own benchmark

bash bench/bench.sh

Test

basher install bats-core/bats-core
bats test/

License

MIT

About

No description or website provided.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages