I have quite a few txt files. They contain the word 'Minimum' (it only shows once in each file), and I want to get the line that contains this word, and show the line in a new file.
To do this, I use this command:

grep 'Minimum' file1.txt > new1.txt     

I did this to each file (file1, file2, etc.), and got lots of newn.txt. But it turns out that some files don't have the word 'Minimum', so their newn.txt are empty. Well, if grep can't get the word, why doesn't Linux give me an error message? Why does it continue and make the newn.txt? Giving me some empty files is really annoying.
So is there a way that I can stop it from creating the newn.txt if it can't find the word?

Also, I'm thinking about putting it into a bash script - the grep command is the first step, and then in the second step I'll do something to the newn.txt. So if grep can't find the word, or if there's an empty file created, I want the script to stop and not to do the second step. Is there a way to do this?

  • grep isn't going to give an error just because the pattern isn't found. It doesn't work in that way. If you have a script and you want it to stop after a certain condition then you need to add its contents to your question. – Nasir Riley Mar 3 '19 at 23:33
  • @NasirRiley The content of the second step or further steps is not the point. The point is that I want to tell Linux to stop from doing the second step if the first step is like that. – XYZ Mar 3 '19 at 23:52
  • You asked why there isn't an error message when the pattern isn't matched and I told you why. The fact that it doesn't stop with an error when you want it to is irrelevant. As I said before, if you want your script to stop when the pattern isn't found then it is up to you to alter the code. It is not up to the operating system or the shell or the binary that you are using to do something that it isn't coded to do or to give an error message when there isn't an error. Add your script to you question and we can help you alter it to get the output that you want. – Nasir Riley Mar 4 '19 at 0:32
  • Actually, when you use the > redirection operator, creating (or opening, if it already exists) the file is the first step, done by the shell before executing the grep command – steeldriver Mar 4 '19 at 0:36
  • @steeldriver Yeah that's right. I've just realised that. – XYZ Mar 4 '19 at 0:43

The shell will create the output file before even running grep. The grep utility will then add contents to the file, if there is anything to add. If grep does not find anything, the file will be left empty.

Another thing that happens if grep does not find anything matching in the input file is that it will exit with a non-zero exit status, signalling "failure". This does not remove the output file, but you could act on the failure to remove the file like this:

grep 'PATTERN' infile >outfile || rm -f outfile

If grep fails to match PATTERN in infile, this would call rm -f to remove the empty outfile. Strictly speaking, this would also try to remove the file if grep failed for any reason (like e.g. not being able to read its input), or if the output file could not be created.

If you additionally want to terminate the script if no matches were found:

if ! grep 'PATTERN' infile >outfile; then
    rm -f outfile
  • Unfortunately it doesn't work here. I tried this command grep 'PATTERN' infile >outfile || rm -f outfile but it doesn't stop and still moves to the next step of my code. My next step is using awk to get a column from the outfile and then put it into a new file. Although grep didn't get the word in infile, awk still got an empty column and created an empty new file. – XYZ Mar 4 '19 at 17:14
  • @LittleG You haven't shown us any part of your script other than the single grep command. We don't know what the rest of your code does or what it looks like. The only thing you said you had an issue with was the creation of the output file from the grep command. If you could edit your question to add a bit more code, then it would be easier for us to see what your code does and how it could be changed. Also, using awk and grep together is seldom needed as awk can do everything grep can do and more. – Kusalananda Mar 4 '19 at 17:19
  • Hiya, I said that in my question - my last sentence reads 'So if grep can't find the word, or if there's an empty file created, I want the script to stop and not to do the second step. Is there a way to do this?' I want it to stop and not start the second step. – XYZ Mar 4 '19 at 17:22
  • @LittleG See updated answer. – Kusalananda Mar 4 '19 at 17:24
  • Thanks. What does the ! mean by the way? I've never seen any exclamation mark after the if – XYZ Mar 4 '19 at 17:28

Try this loop. Adjust it to your needs.

for file in *; do
    line="$(grep -hm1 'Minimum' "${file}")"
    [ -z "$line" ] || echo "$line" > new"${i}".txt

Change * in this line: for file in *; do to your file set.

Take care to weed out any unwanted grep output that might crop up.

  • The loop variable "file" appears to be unused within the loop's body, is that intended? – dhag Mar 4 '19 at 0:02
for i in file*; do grep -q Minimum "$i" && grep Minimum "$i" > "${i/file/new}"; done
  • grep -q Minimum "$i" immediately exists after the first "Minimum" is found
  • the second grep does the real job and is not executed if the first one fails
  • "${i/file/new}" renames file in each filename to new

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.