I’m trying to create a macro on my shell.
The operation I’m trying to automate is this one:
Find all the files containing TEXT_TO_SEARCH, and open them with VSCODE
I can do this with a one-liner
$ code `git grep TEXT_TO_SEARCH | cut -d: -f1 | sort -u`
so my first step was adding the following function to ~/.zshrc
cgrep() {
code `git grep "$1" | cut -d: -f1 | sort -u`
}
and then
$ cgrep TEXT_TO_SEARCH
This works.
Now I’m trying to add an extra feature:
Before opening each file with VSCode, echo to the console "Opening FILE_NAME"
First I’ve tryied this
cgrep() {
grep_results=`git grep "$1" | cut -d: -f1 | sort -u`
for file in $grep_results; do
echo "Opening $file"
code $file
done
}
Note that grep_results
is a "vertical list" i.e.
$ echo $grep_results
src/path1/FILE1.py
src/path2/FILE2.py
src/path3/FILE3.py
This way the for loop considers the first file
as the whole grep_results
and it opens FILE3.py
(not src/path3/FILE3.py
).
I’ve also tryied this (with the help of GPT)
cgrep() {
grep_results=`git grep "$1" | cut -d: -f1 | sort -u`
echo "$grep_results" | while read -r file; do
echo "Opening $file"
code "$file"
done
}
This way I can open just the first grepped file, and I get a message I don’t want from VSCode and I don’t actually understand
$ cgrep TEXT_TO_SEARCH
Opening src/path1/FILE1.py
Run with 'code -' to read from stdin (e.g. 'ps aux | grep code | code -').
2
Answers
Solved, with the help of @Gilles 'SO- stop being evil' in Unix&Linux StackExchange (his full answer here).
This is my final version
Your loop is executed exactly once (as you can see when you run the code with
-x
turned on), because you have only a single variable in the list,$grep_results
. You could split the variable on white space (i.e. the newlines in the variable) by writingbut this still would fail, if one of the files contains embedded spaces. This problem also exists in your own "final version", where you replaced the variable by an array.
What you really want to do, is follow your original approach, but split the result of your pipeline by newlines and not white space: