Ask HN: What command line tool do you wish existed?

2 points by yesenadam ↗ HN
Describe a command line tool you don't have but would love to have. If it already exists, replies can link to it. If it doesn't exist, maybe someone here can write it. Win/win :-)

7 comments

[ 20.5 ms ] story [ 3729 ms ] thread
Something to search through files, like "grep", but allowing combinational logic like "find" does. That would allow you to, for example, find files that contain "remote", and, "machine learning".

Obviously this can be done with a little Python/Bash script, but a command line utility that supports this would be nice.

I was going to write this utility myself, until the part where I had to implement the parsing of the combinational logic (since it can be arbitrarily nested/chained), and I didn't find tools in the language of my choice (Rust) back then to make that easy.

I did find a rust library to do just that yesterday[0], so I myself might get on it!

[0] https://github.com/zesterer/chumsky

uh...

$ grep remote files/* | grep "machine learning"

you're welcome?

That would only catch files with "remote" and "machine learning" on the same line, right?
Fixed:

$ grep -l remote files/* | xargs grep -l "machine learning"

> allowing combinational logic like "find" does

You can still use `find` expressions for this if you really want to use them, but the above seems better for this.

$ find files -type f -exec grep -q remote {} \; -exec grep -q "machine learning" {} \; -print

Combining and using null terminators in the pipe:

$ find files -type f -exec grep -lZ remote {} + | xargs -0 grep -l "machine learning"

Using zsh extended globs:

$ printf '%s\n' files/**(.e['grep -q remote "$REPLY"']e['grep -q "machine learning" "$REPLY"'])

There are multiple options, but the ones that are basically `grep -l | xargs grep` seem best.

Thanks for providing these! I do think these become unwieldily when you want something like "X and Y and not Z and (A or B)" right?

Not only that, I think implementing "or" logic would be quite convoluted by itself right?

Not really. For regexes, "or" is particularly simple, since you can just use `|` in the regex. I would do this:

$ grep -l X files/* | xargs grep -l Y | xargs grep -L Z | xargs grep -El 'A|B'

Here's an awk solution that avoids `|` in the regex:

$ find files -type f -exec awk '/X/{x=1} /Y/{y=1} /Z/{z=1} /A/{a=1} /B/{b=1} END { if (x && y && ! z && (a || b)) print FILENAME }' {} \;

Depending on what your files look like, joining the lines in the files may also be an option:

$ find files -type f -exec awk 'BEGIN{a=FILENAME}{a=a" "$0}END{print a}' {} \; | awk '/X/ && /Y/ && ! /Z/ && (/A/ || /B/) { print $1 }'

I imagine being able to write expressions like the one on this last one is what you're looking for.

All this isn't to say that there isn't space for a new tool. Certainly a tool can be made that allows expressing these more succinctly if you really want it.

Thanks for all this! I really like the first `grep` solution. Dunno how I didn't think of that myself ...