1

I would like to insert a string in line 2 of every file that contain a specific string somewhere in the file.

Like sed '1 a #This is just a commented line' -i

but only if file contains the string:
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-7">

1 Answers1

2

Assuming that your command,

sed -i '1 a #This is just a commented line'

works for a given file.

To apply this to some file, somefile, if the file contains the string <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-7">, you may use

if grep -q -F '<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-7">' somefile
then
    sed -i '1 a #This is just a commented line' somefile
fi

The -q option to grep causes the utility to stop at the first match, and to not output anything (we're only interested in the exit status). The -F option will make grep treat the given pattern as a string rather than as a regular expression.

To apply this to all files in the current directory (skipping files that are not regular files or symbolic links to regular files):

pattern='<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-7">'

for name in ./*; do
    [ ! -f "$name" ] && continue
    if grep -q -F -e "$pattern" "$name"; then
        sed -i '1 a #This is just a commented line' "$name"
    fi
done

I'm using -e "$pattern", with the -e option, here. It's a good habit to specify the pattern for grep with -e when the pattern is kept in a variable. There may be situation where the variable's value starts with a dash (not in this specific problem, obviously), and this would confuse grep if -e is not used, making it think that the pattern is actually some command line option.

To do this for all files in or below the current directory:

pattern='<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-7">'

find . -type f -exec sh -c '
    pattern=$1; shift
    for name do
        if grep -q -F -e "$pattern" "$name"; then
            sed -i "1 a #This is just a commented line" "$name"
        fi
    done' sh "$pattern" {} +

This executes a short inline sh -c script for batches of found files, passing the pattern as the first command line argument to the script and the found pathnames as the remaining arguments.

or, to let find use grep as a test and then execute sed on the files that passes the test,

pattern='<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-7">'

find . -type f \
    -exec grep -q -F -e "$pattern" {} \; \
    -exec sed -i '1 a #This is just a commented line' {} +

By using {} + instead of {} \; at the end of the sed command above, we give sed as many input files as possible at once rather than executing sed once for each file. This requires GNU sed to work properly, but since you're already using GNU sed syntax in your a command, I'm assuming that is ok.

See also Understanding the -exec option of `find`

Kusalananda
  • 333,661