4 ms·
Something to search through files, like "grep", but allowing combinational logic like "find" does. That would allow you to, for example, find files that contai
by davidatbu 5y ago
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 https://github.com/zesterer/chumsky
- dossy 5y agouh... $ grep remote files/* | grep "machine learning" you're welcome?
- davidatbu 5y agoThat would only catch files with "remote" and "machine learning" on the same line, right?
- jolmg 5y agoFixed: $ 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.
- davidatbu 5y agoThanks 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?
- jolmg 5y agoNot 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.
- davidatbu 5y agoThanks for all this! I really like the first `grep` solution. Dunno how I didn't think of that myself ...