Monday, April 4, 2022

[SOLVED] How to print the file names from which I grep some lines

Issue

I'm trying to get some lines from several json files using the following code:

cat $(find ./*/*/folderA/*DTI*.json) | grep -i -E '(phaseencodingdirection|phaseencodingaxis)' > phase_direction

It worked! the problem is that I don't know which line comes from which file

With this find ./*/*/preprocessing/*DTI*.json -type f -printf "%f\n" I can print those names, but they appear at the end and not in order with their respective phaseencodingdirection|phaseencodingaxis extracted lines.

I don't know how to combine those lines of code to print the file's name from which the line was extracted and their respective extracted lines!?

Could you help me?


Solution

the problem is that I don't know which line comes from which file

Well no, you don't, because you have concatenated the contents of all the files into a single stream. If you want to be able to identify at the point of pattern matching which file each line comes from then you have to give that information to grep in the first place. Like this, for example:

find ./*/*/folderA/*DTI*.json |
        xargs grep -i -E -H '(phaseencodingdirection|phaseencodingaxis)' > phase_direction

The xargs program converts lines read from its standard input into arguments to the specified command (grep in this case). The -H option to grep causes it to list the filename of each match along with the matching line itself.

Alternatively, this variation on the same thing is a little simpler, and closer in some senses to the original:

grep -i -E -H '(phaseencodingdirection|phaseencodingaxis)' \
    $(find ./*/*/folderA/*DTI*.json) > phase_direction

That takes xargs out of the picture, and moves the command substitution directly to the argument list of grep.

But now observe that if the pattern ./*/*/folderA/*DTI*.json does not match any directories then find isn't actually doing anything useful for you. There is then no directory recursion to be done, and you haven't specified any tests, so the command substitution will simply expand to all the paths that match the pattern, just like the pattern would do if expanded without find. Thus, this is probably best of all:

grep -i -E -H '(phaseencodingdirection|phaseencodingaxis)' \
    ./*/*/folderA/*DTI*.json > phase_direction


Answered By - John Bollinger
Answer Checked By - Marie Seifert (WPSolving Admin)