-2

I am trying to write a script which will check to see if the contents of a file match a certain value and if so, overwrite it with contents of another file.

Example:

file1 =

A, B, C, D  
1, 2, 3, 4

file2 =

E, F, G, H  
5, 6, 7, 8
  1. Checks to see if grep of file1 = A, B, C, D
  2. If yes, cat file2 and write output back to file 1
  3. If no, echo "Setting already configured" and exit

Here is what I have:

#!/bin/bash

var01=$(cat /home/user/scripts/test01.txt | grep A)
var02=$(cat /home/user/scripts/test02.txt)


if [[ $var01 = "A, B, C, D" ]];
then
  [[ echo $var02 > /home/user/scripts/test01.txt ]]
else
  echo "Setting already configured"
fi

I keep getting the following errors for line 9:

line 9: conditional binary operator expected
line 9: syntax error near `$var02'
line 9: `  [[ echo $var02 > /home/user/scripts/test01.txt ]]'

Any pointers would be greatly appreciated. Thanks.

2
  • 3
    Don't use [[ ]] around the echo command -- square brackets make their contents a conditional expression, not a command, but echo is a command. Also, double-quote your variables: use echo "$var02" instead of echo $var02. shellcheck.net is good at spotting common mistakes like this, so I recommend running your scripts through it and fixing what it points out. Commented May 15 at 2:04
  • Also it's unclear what you're trying to do, you said "Checks to see if grep of file1 = "A, B, C, D"", but then you're grepping just for A
    – kos
    Commented May 15 at 2:09

3 Answers 3

2

So, it looks like that you want to copy test02.txt to test01.txt if test01.txt has one and only one line that contains A and that line is A, B, C, D.

Then maybe that should be something like:

#! /bin/sh -

if
  matching_lines=$(grep A test01.txt) &&
    [ "$matching_lines" = 'A, B, C, D' ]
then
  cp test02.txt test01.txt
fi

Beware that except in zsh, shells can't store NULs into their variables. If some lines containing A also contain NULs, the behaviour will vary between shells. bash removes the NULs in command substitution, so you may get a false positive if test01.txt contains A\0\0\0\0\0, B, C, \0\0D for instance.

Note that the above always scans the whole file from beginning to end. Since you know the conditions don't match as soon as a line other than A, B, C, D is seen containing A or as soon as any line containing A is found after the right one has been found, you could optimise it with something like:

if
  awk '
    /A/ {
      if (found) {found = 0; exit}
      if ($0 == "A, B, C, D")
        found = 1
      else
        exit
    }
    END {exit !found}' test01.txt
then
  cp test02.txt test01.txt
fi

With several awk implementations including gawk and modern versions of mawk, that also works around the NUL character problem described above.

2
#!/bin/bash
#   -q makes grep not give any output AND quit after finding a first match
# 
if grep -q 'A, B, C, D' /home/user/scripts/test01.txt
then
    cp /home/user/scripts/test02.txt /home/user/scripts/test01.txt
else
    echo "Setting already configured"
fi
5
  • A few comments on this. Both GNU and BSD grep stop reading after one match with the -q flag, so the -m1 is unnecessary. You should use cp rather than cat and a redirect. And I think you have your then and else actions swapped, it should overwrite the file if the match is found.
    – Kevin
    Commented May 24 at 19:33
  • BSD and GNU cp both explicitly preserve permissions on existing files by default.
    – Kevin
    Commented May 24 at 19:39
  • @Kevin you're right in both. I'll change the answer.
    – humance
    Commented May 26 at 8:41
  • @Kusalananda, re: your edit, with the arguments flipped that would be wrong in GNU grep as well, only grep -q file -e pattern would work in GNU grep (in non-POSIX environment) and not POSIX compliant implementations. With grep -q file pattern, file is taken as the pattern and pattern as the file, there's no way for grep to known that pattern is meant to be a pattern and not a file. Commented May 27 at 7:26
  • @StéphaneChazelas Yes, thanks. A have updated the revision comment.
    – Kusalananda
    Commented May 27 at 7:44
2
#!/bin/bash

if [ "$(grep A /home/user/scripts/test01.txt)" = "A, B, C, D" ]; then
  cp /home/user/scripts/test02.txt /home/user/scripts/test01.txt
  echo "Setting configured."
  exit 0
fi

echo "Setting already configured."

exit 1

You were on the right track.
I just changed the else to follow through to exit 1 and "success" will return 0. (i.e exit 0)

1
  • 1
    @kos Good point, there's no need for $var2 at all, test02.txt is never modified. It looks like a "default" setting, so to speak.
    – JayCravens
    Commented May 26 at 23:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .