Shell Script to sed with Multiple Files

I am not sure what I am doing wrong here. The code should work fine. I have been making small changes insuring that each new bit works. Now running my sed through multiple files I am getting incorrect output. Any help and instruction would be greatly appreciated.

The problem -
Generalize your sub2 script, producing a new script sub3 that will apply a substitution to any number of files given on the command line. For example

~/UnixCourse/scriptAsst/sub3 foo bar myFile1.txt myFile2.txt
myFile3.txt

should apply the same substitution throughout each of the three files named there.
Give the command:

~cs252/bin/scriptAsst.pl

to complete the assignment.

My code -

#!/bin/sh

p1="$1"
shift
p2="$1"
shift
p3="$1"
shift

for FILE in "$@"
do
        echo $p1
        echo $p2
        echo $p3

        #echo "$p1" | sed -e 's/\([*.[^$]\)/\\\1/g' > temp
        #p1="`cat temp`"
        #rm temp
        #echo $p1

        sed "s/$p1/$p2/g" "$p3" > temp.out
        mv temp.out "$p3"
done

Results -

sub3 produced incorrect output on test 28: /home/cbliss/UnixCourse/scriptAsst/sub3 '3' '9' '_aardvark.cpp'

I do not know what test 28 inputs or the contents of _aadvark.cpp. We run a given command and it automatically tests our script. If it passes a test we see:

1...
2...
3... etc.
  1. Complete Name of School (University), City (State), Country, Name of Professor, and Course Number (Link to Course):

Old Dominion University - Norfolk, Va USA
Professor Steven Zeil
CS 252 - An Introduction to Unix for Programmers

Have you noticed that you're setting $FILE in your while loop but you never refer to it?
Does the example below give you any ideas on how to proceed:

#!/bin/sh
p1="$1"
shift
p2="$2"
shift

for FILE in "$@"
do
        echo $p1
        echo $p2
        echo "Process $FILE using $p1 and $p2..."
done

Okay, I changed the code to

#!/bin/sh

p1="$1"
shift
p2="$1"
shift

for file in *
do
      echo $p1
      echo $p2

      sed "s/$p1/$p2/g" $file >temp.out
      mv temp.out $file
done

And received the error

sub3 appears to be treating its first parameter as the name of a file to be edited.

for test 28.

So then I changed my script to -

#!/bin/sh

p1="$1"
shift
p2="$1"
shift
p3="$1"
shift


for file in *
do
      echo $p1
      echo $p2
      echo $p3

      sed "s/$p1/$p2/g" "$p3" > temp.out
      mv temp.out "$p3"
done

Which passes test 28, but fails test 29 and does not address what you were saying.

How would I go about referring to file? Setting $p3=file while inside the loop? The one example in the slides we have is

for file in *
do
  echo Looking at $file.
  count=`expr $count + 1`
  echo Count is $count.
done

And it uses that snippet repeatedly.

And the failed test output is -

sub3 produced incorrect output on test 29: /directory/sub3 'e' 'x' '_bongo.dat' '_cat.dat'

I think I see what is wrong here, having 3 argument parameters and it giving four, but how do I account for X number of files?

Did it look like you were getting the correct set of arguments to give to sed when you tried my sample script? (Did you try my sample script before changing it?)

Why did you change:

for FILE in "$@"

in your original code and in my example to:

for FILE in *

The shell expands "$@" to a list of the quoted arguments remaining on your command line after the shift commands removed your first two command-line arguments. The shell expands * to a list of files in the current directory.

Using

for FILE in "$@"

I get the error

sed can't read : No such file or directory
mv: cannot move `temp.out' to `': No such file or directory

What I have with your recommended changes -

#!/bin/sh

p1="$1"
shift
p2="$1"
shift
#p3="$1"
#shift

for FILE in "$@"
do
        echo $p1
        echo $p2
        set p3="$file"
        echo $p3

        #echo "$p1" | sed -e 's/\([*.[^$]\)/\\\1/g' > temp
        #p1="`cat temp`"
        #rm temp
        #echo $p1

        sed "s/$p1/$p2/g" "$p3" > temp.out
        mv temp.out "$p3"
done

I repeat: Did you try my sample script before changing it?

Please try the sample script I gave you without changing it. (Note that there is a HUGE difference between $FILE and $file .) Using:

for FILE in whatever

and referencing $file in the loop won't work.

I hadn't even realized that I was using

FILE

and

$file

. My apologies. So, this is my code at present:

#!/bin/sh

p1="$1"
shift
p2="$1"
shift

for FILE in "$@"
do
        echo $p1
        echo $p2
        echo "Process $FILE using $p1 and $p2..."

        #echo "$p1" | sed -e 's/\([*.[^$]\)/\\\1/g' > temp
        #p1="`cat temp`"
        #rm temp
        #echo $p1

        sed "s/$p1/$p2/g" $FILE > temp.out
        mv temp.out $FILE
done

Running

~cs252/bin/scriptAsst.pl

This is the output -

Checking sub3...
28...
29...
30...
31...
sed: can't read _king: No such file or directory
sed: can't read cobra.dat: No such file or directory
mv: target `cobra.dat' is not a directory
32...
33...
sed: can't read _king: No such file or directory
sed: can't read cobra.dat: No such file or directory
mv: target `cobra.dat' is not a directory

sub3 produced incorrect output on test 33: /home/cbliss/UnixCourse/scriptAsst/sub3 'Unix' 'U N I X' '_king cobra.dat' '_ne$wt.foo'

In your original script (which was passing many more of the tests), you had:

        sed "s/$p1/$p2/g" "$p3" > temp.out
        mv temp.out "$p3"

Now you have:

        sed "s/$p1/$p2/g" $FILE > temp.out
        mv temp.out $FILE

Other than changing p3 to FILE, what else changed?

Did you notice that the error reports you got included:

sed: can't read _king: No such file or directory
sed: can't read cobra.dat: No such file or directory
mv: target `cobra.dat' is not a directory
        and
sub3 produced incorrect output on test 33: /home/cbliss/UnixCourse/scriptAsst/sub3 'Unix' 'U N I X' '_king cobra.dat' '_ne$wt.foo'

Do you see that the diagnostic messages from sed and mv refer to parts of one of the parameters passed to your script? Could changing quotes around arguments passed to sed and mv have an effect leading to the errors you're seeing?

Thank you :slight_smile: problem solved and assignment passed. Again, thank you. You were very helpful.

Hey is this thread still open, i ran the code and am having trouble with line 37 of the file going through, am i allowed to post my code and recieve help?

With the title having changed to have [SOLVED] in it, I would suggest that you open a new one and refer to this.