Execution Problems with sed

Use and complete the template provided. The entire template must be completed. If you don't, your post may be deleted!

  1. The problem statement, all variables and given/known data:
    Okay so I am taking bash scripting this semester and we are now working on the stream editor sed. For our book we are using Bash Guide for Beginners

In Chapter 5 exercise numbers
2. Make a list of files in /usr/bin that have the letter "a" as the second character. Put the result in a temporary file.

  1. Delete the first 3 lines of each temporary file[/b]

I did solution number 2 I just have to figure out solution number 3
On solution number 2 I typed in

ls /usr/bin/?a* | cp /usr/bin/?a* /tmp

  1. Relevant commands, code, scripts, algorithms:

to delete a line using sed you type in
sed '3d' example.txt

  1. The attempts at a solution (include all code and scripts):

So If I type

sed '3d' /tmp

It dont work for the files in the directory
I cant figure out how to do it for all the files in directory at the same time.

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

Oklahoma State University Institute of Technology
Okmulgee, Oklahoma
U.S.A
Professor: Mr Fil Guinn
Course Number: ITD-2313

Note: Without school/professor/course information, you will be banned if you post here! You must complete the entire template (not just parts of it).

---------- Post updated at 10:13 AM ---------- Previous update was at 10:08 AM ----------

I think I may have messed up I put it in a directory instead of a file

That is correct. You needed to pass a filename to sed - not a directory.

Go into the directory and run this

# for file in *; do sed '3d' $file; done

Hope it Helps.
Cheers!

Lets go over this as you have already found out you are doing something wrong. Your code:

ls /usr/bin/?a* | cp /usr/bin/?a* /tmp

It pays to examine a complicated pipeline-command step by step. You already found out the correct filemask "?a*" to filter out the files you are interested in. Now execute the command

ls /usr/bin/?a*

and have a look at what it does. To get a more verbose listing let us use the "-l" option of "ls":

ls -l /usr/bin/?a*

You wanted a "list of the files ...". Is this your list? Do you need to work on the list any further? If "no" you are finished. Just save the result to a file using redirection. You know about redirection, yes? (If not: just ask.)

If "yes", you need to still work on the list, lets have a look at the second part of your command:

| cp /usr/bin/?a* /tmp

Let us first talk about pipelines ("|"): Unix processes are like garden hoses with the data acting as water: you fill something in, it is in some way worked on inside, finally something (else) comes out. Where the data goes in is a special device called "stdin" where data comes out is called "stdout". Every process has these facilities. What a pipeline does is simple: it connects the <stdout> of the first process to the <stdin> of the second.

Here is an example on how this works: consider the command "echo", which displays text. Enter

echo abcdefg

on the commandline to have "abcdefg" displayed. In fact it works this way: "echo" puts everything given as commandline option to it (the text) to its <stdout>, which happens to point to the display *). Therefore the text gets displayed. Could the output be rerouted? Oh, yes! We can use this data stream to put it to the next utility, lets say "tr". "tr" works as a text filter and gets two arguments: a character it searches for in the datastream and a character it replaces the character with.**)

Now lets try to use this knowledge in a pipeline:

echo abcdefg | tr a Z

It works like this: echo produces its data stream "a-b-c-...." and puts it to <stdout>. As this is connected to "tr"s <stdin> it is not displayed but "tr" works on it, replacing every "a" with a "Z". Then the resulting data stream "Z-b-c-...." is put to "tr"s <stdout>. As this is not redirected it points to the display and hence it is displayed.

Now lets reexamine what you have done: you produced a data stream consisting of some file names with "ls". Then you piped these to "cp", a utility which copies files. "cp" does not know how to work on datastreams because it only works on commandline options. So "cp" simply throws away the "garbage" input it can't work with and examines its command line:

cp /usr/bin/?a* /tmp

This tells "cp" to select all files of the form "/usr/bin/?a*" and copy these to "/tmp". Exactly this is what happened - it did copy the files.

I hope this helps.

bakunin
_________
*) I skip the details of device handling here to make it simple. For the purpose of the problem at hand this simplification is sufficient.

**) In fact "tr" can do more, but this would just confuse things.

Thank you for the info bakunin. This is a hard course for me since I have no programming background. It is fun to learn but frustrating at times.