Editing a file using a script

Hi

I have about 10 config files belonging to software that runs on SCO UNIX. These files contain, amongst many other things, a path which points to the software locations. We normally have to change them manually every time the software is coppied to a new location and when you gotta do a few times a day, it becomes quite laboreous.

I would like to know how to change all these paths using a single script. I'm hoping to have the user enter the 2 different paths once and let the script find the paths in these files (line numbers for the paths vary from file to file) and over write them with the new ones.

It is worth noting that the only alterations that can be made to the config files are the path names. Anything else will cause the software that reads them, to disappear up its own backside.

I hope I'm being clear and I look forward to some help :slight_smile:

When you deploy your software, do you also have a common directory structure associated with it? For instance, if I were to deploy to /home/my-user, would there be common directories under /home/my-user such as sh, log, bin, files? If so, you could develop a common approach to deployment by having your user enter in the common path to the directory.

For example:

#My Deployment Script

echo "Enter Deployment Directory"
read DEPLOY_DIR

if [ ! -d $DEPLOY_DIR ]
then
echo "$DEPLOY_DIR Not A Directory"
exitt 1
fi

export UNIX_ENV=$DEPLOY_DIR

. $UNIX_ENV/envFile #Source in the environment file

#envFile
#Add all path variables to the env file so
#that you never have to change a path #again!

export SH_PATH=$UNIX_ENV/sh
export BIN_PATH=$UNIX_ENV/bin
export LOG_PATH=$UNIX_ENV/log

If this is not an option, then you can used sed to change all of the paths based upon user input. There will be a little effort to ensure your changing the correct line in each file. This can easly be overcome by tagging the line in each file that you want to have changed. Make sure that before you change your original file that you make a backup!

Thanks for your reply google.

Unfortunately I'm only a junior manager here and making changes to the software code itself isn't an option in my position unfortunately...

the second way you propose is more up my street, but I'm not sure how to use the sed command. I've been working with UNIX for 2 days now :slight_smile:

I have written the script that coppies the software and the 10 files in queswtion, but it's a royal pain to edit these files every time. See my problem?

Edit: replied to wrong thread

As far as I understand sed can meet your requirements or you can even do a global replace in vi.
Open the file using vi ,type escape followed by : then type
s/Oldpath/newpath/g .This should change the path through out the file.Also note that if your path contains "/" ,then you will have to escape it using a "\"
For example:

s/old_dir1\/old_dir2\/old_dir3/new_dir1\/new_dir2\/new_dir3/g

alternately you can use sed
sed 's/old_dir1\/old_dir2\/old_dir3/new_dir1\/new_dir2\/new_dir3/g' filename >new_filename
Also if you want to pass the pathnames as argument then you can type a script containing sed which takes the path as arguments
I haven't tried the last solution,but I don't see any major problem with it.

Hope this helps
Saurabh

Wouldn't you have to edit the script with the old and new directories every time? (which kinda defeats the purpose)

There are 152 variations (groups) of these 10 files knocking about in several servers and you choose at random a group of 10 to modify. None of the 152 variations are the same...

Just to throw a spanner in the works and confuse everyone :smiley:

Here is the problem as I understand it.

  1. You have a ton of scripts that have hard coded paths
  2. Each time a new deployment occurs, you must edit the paths
  3. Your sick of manually editing the paths!

Proposal:

-- Create a script that anyone can use that will do the following.

  1. Copy the files in questions (deploy them were they need to be)
  2. For each file and path that needs a change, Prompt the user with the existing directory paths. Ask user if this is correct (if so, exit) if not ask user to specify the path.
  3. Validate the users input.
  4. Backup the original config files that you are about to change.
  5. Use sed to change the path by replacing the old path in the file with what the user just requested.
  6. Work on a more robust deployment plan :slight_smile:

Here is a link to some sed info to get you started

:smiley: :smiley: :smiley:

thanks google, the link has really helped!

Okay so if I'm following all this correctly..

1 You've got 10 text files which have almost all the same information in each file, except for two lines which contain a path.
2 These two lines with the path names on them are not necessarily on the same line each time you copy a file and edit it, presumably because each of the 10 text files is set up slightly differently..

Maybe a loop..? In ksh:

cd "your/dir"
echo "Enter the two directories:"
read dirOne
read dirTwo
for FILE in `ls`
do
  foundFirstDir="no"
  while read LINE
  do
    echo $LINE | grep -q "/"
    if [[ $? -eq 0 ]]
    then
      if [[ $foundFirstDir = "no" ]]
        then
        echo $dirOne >> ${FILE}_new
        foundFirstDir="yes"
      else
        echo $dirTwo >> ${FILE}_new
      fi
    else
      echo $LINE >> ${FILE}_new
    fi
  done < $FILE
done

Basically, I'm assuming the only lines in the entire file that will contain a backslash are the two lines that contain the paths on them.. is it safe to make this assumption?

Thanks oombera. I can pretty much guarantee that the directory will always be in the following format:

/u/[variable directory]/pfx/
and
/u/[variable directory]/main/

it is the [variable directory] bit that needs changing all the time.

would the script be more accurate if instead of
echo $LINE | grep -q "/"

I had
echo $LINE | grep -q "/u/"

I'll try it now, both ways and keep you posted :wink:

Edit1: I'm not entirely sure what dirOne and dirTwo are..? Source and Target?

./test: [[: not found

I get that error about 20 times in succession...

Try going back into the script and removing one set of brackets.. i.e. where you see [[ something ]], remove a set of brackets so you have [ something ].

Yes, the more characters you can put in the grep command, the more likely you are to find the exact lines you're looking for.

You said you want the user to enter two directories when they run the script. The script stores those two directories in $dirOne and $dirTwo. That way, when the script finds what appears to be directories in the configuration file, it will replace the first one it finds with $dirOne and the second one with $dirTwo.

What shell are you using? (If you don't know, try echo $SHELL and post the results..)

Shell:
# echo $SHELL
/bin/sh

It hasn't worked either :frowning:
The program ran, it seemed to be doing something for a few moments, then returned to prompt. Checked the files and they are unaltered...

That may be a good sign .. no errors concerning the brackets!

If you look at my script, it isn't designed to overwrite your files.. it's designed to create new files ending with _new. So if your configuration file is named configFile01, then after running my script you should see a configFile01_new in the same directory.. are they there?

Oh duh! Sorry :slight_smile:

Yes! It worked! I had to edit the path it was searching for as it was changing things I didn't want it to change.

Would it be possible to change the code so that I only enter one directory (I will run the script on an individual directory basis) and also to simply over write the file it is editing?

I have a test system I'm running on so it doesn't matter if I break it. :slight_smile:

If you want to overwrite the file, replace the three references to ${FILE}_new with TMP_00 and add this bit of code to the bottom of the script:

    else
      echo $LINE >> TMP_00
    fi
  done < $FILE
  mv TMP_00 $FILE
  rm TMP_00
done

Not quite sure what you mean by this though.. could you rephrase the question?

From what I have understood in your script, you enter two directories at the top and the script finds an entry which I specify (in this case LOC=/u/) and changes the first entry it finds to dirOne and the second one it finds to dirTwo?

If that's right, I would like to enter just one directory and have the script change entries which contain LOC=/u/[blah]/main to LOC=/u/dirOne/main.

I hope I'm doing a good job explaining... :expressionless:

Yes, that can work too.. see if this works:

echo -n "Enter a directory: "
read DIR
for FILE in `ls`
do
  while read LINE
  do
    echo $LINE | grep -q "/u/.*/main/"
    if [ $? -eq 0 ]
    then
      echo "/u/$DIR/main/" >> TMP_00
    else
      echo $LINE >> $TMP_00
    fi
  done < $FILE
  mv TMP_00 $FILE
  rm TMP_00
done

This could be done really quickly with a sed command:

echo -n "Enter a directory: "
read DIR
for FILE in `ls`
do
  sed -e 's/\/u\/.*\/main\//\/u\/'$DIR'\/main\//g' $FILE
done

but unfortunately to enter a directory like this/ismy/directory you'd have to type it in as this\\\/ismy\\\/directory

Sorry if this is mentioned above, I was trying to follow the whole "conversation"...

Does the script change between the times you deploy from one location to another?

You could use a "skeleton" script and only edit the variables.

Put a key word in the script so that when you deploy it, you only have to edit that key word. Don't change the already deployed script... only edit the skeleton and save it where you want it to be next... (new directory)...

ie I have the following control card detail.src that my users update via script.
R,detail.lis,0,<CO>,?,<DATERNG>,?,?,?,?,?,<ST>,1,0,60

the script prompts the user for a date rangs (from and to) and then a company code and state code then uses the skeleton file as input to create a new file.... :

sed -e "s/<DATERNG>/$DATE1,$DATE2/" \
-e "s/<CO>/$COMPANY/" \
-e "s/<ST>/$STATE/" <detail.src >detail.dat
Everytime it saves out a new file.

Does this help?

I'm not positive if this is what you're asking, but instead of using a skelaton file (I would call it a template) with my script I'm making the assumption that the directory already has some old configuration files in it, which my script essentially is using as templates to create new configuration files...