Adding a line to 1000's of files right after x amt of characters.

I am trying to add a single line of text to every file in a particular folder. There are thousands of files in the folder.

Each file contains this same start of the first line:
{d "%w- %d %m-, %Y - %T"} <some message here>

with the rest of the text following the second curly bracket (where <some message here> is present).

I would like to add this right after the right curly bracket on the first line:
Model_Type={t}, ModelName={m}

(with the option of adding a CRLF after {m})

So the result would look like:
{d "%w- %d %m-, %Y - %T"} ModelType={t}, ModelName={m} <some message here>

Any ideas? MANY THANKS!!!

Try this..

sed 's/}/}Model_Type={t}, ModelName={m}/1' file
1 Like

Assuming that only the first line in each file is the one to be checked for replacement, try:

cd /your/directory
find . -type f -name 'Event*' -exec perl -pi.bak -e 'if($ARGV ne $prev){$prev=$ARGV;s/(\{.*?\})/\1 Model_Type={t}, ModelName={m}/}' {} +

This will edit your files "in-place" with a back-up of each file kept with .bak extension.

1 Like

I'm assuming I can put this line in a script so it might look like:

#!/bin/sh

# read files
cat ${WORKFILE} | while read file
do
sed 's/}/}Model_Type={t}, ModelName={m}/1' $file
done

NOTE: ${WORKFILE} is a text file that has the listing of all the files I want to edit.

---------- Post updated at 02:46 PM ---------- Previous update was at 02:32 PM ----------

After running the above script it is placing "ModelType={t}, ModelName={m}" after EVERY right curly bracket in the file. There are multiple variables in each file, which look like this: {v}. So I am getting multiple incertions in each file.

---------- Post updated at 02:52 PM ---------- Previous update was at 02:46 PM ----------

After putting this in a loop I can see it do two things.
1st: I am getting output to the screen, but it is not writting the addition to the file :frowning:

2nd: The code is adding multiple instances of "Model_Type={t}..." for each file may contain multple instances of variables, which look like: {v} where "v" is the variable letter., so, In the screen output it is adding "Model_Type=..." every time it sees another right curley bracket.

My entire script looks like this:

#!/bin/sh
####### MAIN SCRIPT #################
host=$1
DATE=`date '+%m%d%y_%H%M'`
CLISESSID=$$
SPECROOT=d:/
SCRIPTHOME=${SPECROOT}/custom/scripts/TestEventFolder
WORKFILE=${SCRIPTHOME}/Event_OneLine.txt
#WORKFILE=${SPECROOT}/tmp/worklist.txt
LOGFILE=${SCRIPTHOME}/LOGFILE_${DATE}.txt
SEARCHDIR=${SPECROOT}/Events
CLIMNAMEWIDTH=64
CLIPATH=${SPECROOT}/vnmsh
export CLISESSID CLIMNAMEWIDTH CLIPATH host DATE SPECROOT SCRIPTHOME WORKFILE LOGFILE
 
cd ${SCRIPTHOME}
 
# get event files
ls Event* > ${WORKFILE}

# read files
cat ${WORKFILE} | while read file
do
sed 's/}/}Model_Type={t}, ModelName={m}/1' $file
done

Screen Output:

d "%w- %d %m-, %Y - %T"}Model_Type={t}, ModelName={m} - A "caSwitchLinkUpTrap" event has occurred, from {t} device, named {m}.
caSwitchLinkUp trap signifies that the caSwitchIfOperStatus object for a switch interface left the down state and transitioned into
te). This other state is indicated by the included value of caSwitchIfOperStatus.
aSwitchIfSwitchIndex = {I 1}Model_Type={t}, ModelName={m}
aSwitchIfIndex = {I 3}Model_Type={t}, ModelName={m}
aSwitchIfAdminStatus = {T caSwitchIfAdminStatus 4}Model_Type={t}, ModelName={m}
aSwitchIfOperStatus = {T caSwitchIfOperStatus 5}Model_Type={t}, ModelName={m}
event [{e}Model_Type={t}, ModelName={m}])

As can be seen, when the script is run it is looking for the right curley bracket in EACH LINE of the file. Is there a way to have the sed operation look at the FIRST LINE ONLY?

  1. Nothing extraordinary. sed is a filter; it will not change its input source. Rather it will work on a copy of the input, line-by-line, and produce output. You may redirect that output to a temporary file and then rename that temporary file with the original file. That is actually done by the perl code I'd suggested.

  2. That's because that sed command is faulty (according to your requirement). It's replacing the first occurrence of the closing curly brace with whatever you wanted on every line.

Why don't you try what I've suggested?

EDIT:

Replace this section of your code:

cd ${SCRIPTHOME}

# get event files
ls Event* > ${WORKFILE}

# read files
cat ${WORKFILE} | while read file
do
sed 's/}/}Model_Type={t}, ModelName={m}/1' $file
done

with

cd ${SCRIPTHOME}
perl -pi.bak -e 'if($ARGV ne $prev){$prev=$ARGV;s/(\{.*?\})/\1 Model_Type={t}, ModelName={m}/}' Event*

Sorry about not trying it.... I just took the first suggestion and went with it.
Follow up Question for you:
Can your method be placed in a script so that I can use a loop function, or will the command line version simply do what I want to do for every file?

Thanks for your help!!!!!

Check Post #5 again (I've added some things).

Boy... that simple find command did EXACTLY what I needed!!!!

Many many thanks!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

:):):):):):):):):):slight_smile:

---------- Post updated at 03:13 PM ---------- Previous update was at 03:09 PM ----------

Could you explain what is happening so that I won't ask the same stupid question next time, and so I'll be able to explain it to other people... ?

This Perl one-liner will read a line at a time from the files provided to it (by the shell by expanding Event* ; I hope there are only regular files matching that pattern). The name of the current input file will be in the variable $ARGV . To identify the first line of a file, the variable $prev is used. When this variable is not the same as $ARGV , it means the first line of the new file. In this line, the required substitution is made. That is, the first block of data between { and } is matched (through the non-greedy quantifier *? ; for more info, use Google) and captured. This is then used (as \1 ), followed by the required string, in the replacement string.

1 Like

THANK YOU SO MUCH FOR HELPING ME OUT!!! :smiley:

Is there a way to check to see if a file ALREADY has the additional line in it so that it doesn't add another line?