I am using a Linux command to find all files with the .txt and .cmd extensions inside a root folder, excluding files located in subdirectories named “Sub Processes” and “SubProcesses.” The current command I use is:
find . ( -name '*.txt' -o -name '*.cmd' ) ! ( -path '*/Sub Processes/*' -o -path '*/SubProcesses/*' )
Now, I want to refine this command so that only the .txt files that contain INSIDE THEM the string “starter” are displayed in the output, while still including all .cmd files as is.
I attempted to find a solution online and through AI engines but haven’t been successful. Is there a way to apply the -exec grep ‘starter’ command only to the .txt files, ensuring they are the only ones checked for this string(inside the file itself) in the output?
Note: I dont want to open a new Bash or Shell interpreter while executing the command.
1
You can use grep
in the find
command :
find . ! ( -path '*/Sub Processes/*' -o -path '*/SubProcesses/*' ) ( -name '*.cmd' -o -name '*.txt' -exec grep -q starter {} ; ) -print
1
Instead of testing every path against SubProcesses
, it’s better to use -prune
to avoid even reading these directories, before looking for our name patterns:
find . -name 'Sub Processes' -prune
-o -name 'SubProcesses' -prune
-o -name '*.txt'
-o -name '*.cmd'
(I’ll assume we’re using GNU coreutils throughout this answer, since that’s most likely on Linux systems).
Now we need to change the actions associated with the two matches instead of printing:
- for the first one, we can execute a
grep
to print the names of files containing matches:-exec grep -F -l starter {} +
, and - for the second, we just need to print it:
-print
.
The resultant command is
find .
-regex '.*/Sub ?Processes' -prune
-o -name '*.txt' -exec grep -F -l starter {} +`
-o -name '*.cmd' -print
Note that the -exec … +
used here is more efficient than -exec … ;
, as it uses the minimum number of sub-processes, rather than starting a new grep
for each file.