views:

120

answers:

5

Hey,

I want to write a very simple script , which takes a process name , and return the tail of the last file name which contains the process name.

I wrote something like that :

#!/bin/sh
tail $(ls -t *"$1"*| head -1) -f

My question:

  1. Do I need the first line?

  2. Why isn't ls -t *"$1"*| head -1 | tail -f working?

  3. Is there a better way to do it?

+6  A: 

1: The first line is a so called she-bang, read the description here:

In computing, a shebang (also called a hashbang, hashpling, pound bang, or crunchbang) refers to the characters "#!" when they are the first two characters in an interpreter directive as the first line of a text file. In a Unix-like operating system, the program loader takes the presence of these two characters as an indication that the file is a script, and tries to execute that script using the interpreter specified by the rest of the first line in the file

2: tail can't take the filename from the stdin: It can either take the text on the stdin or a file as parameter. See the man page for this.

3: No better solution comes to my mind: Pay attention to filenames containing spaces: This does not work with your current solution, you need to add quotes around the $() block.

theomega
Did you mean "2. `tail`" by any chance?
Matt Ball
Yeah, strange markup-error, sometimes I don't understand markup!
theomega
Ok, but does the first line mandatory ? the shell that i'll run the script from would run the script anyway. i'm running the script from shell.So my question is what do I need the first line for ?
Idan
@Idan think of that first line as telling the OS what program to use to run your script. So instead of running it by calling "sh myscriptname" you can run it just by typing in "./myscriptname" or "myscriptname".
JohnK813
+2  A: 

$1 contains the first argument, the process name is actually in $0. This however can contain the path, so you should use:

#!/bin/sh
tail $(ls -rt *"`basename $0`"*| head -1) -f

You also have to use ls -rt to get the oldest file first.

Marc Schütz
Even though there is some ambiguity in the question "takes A process name [...] file name which contains THE process name" I interpret it as "takes A process name [...] file name which contains THAT process name" so it's $1 and not $0 we're referencing to.
conny
Oops, you're right - somehow I overread that first part...
Marc Schütz
A: 

Following on from @theomega's answer and @Idan's question in the comments, the she-bang is needed, among other things, because some UNIX / Linux systems have more than one command shell.

Each command shell has a different syntax, so the she-bang provides a way to specify which shell should be used to execute the script, even if you don't specify it in your run command by typing (for example)

./myscript.sh

instead of

/bin/sh ./myscript.sh

Note that the she-bang can also be used in scripts written in non-shell languages such as Perl; in the case you'd put

#!/usr/bin/perl

at the top of your script.

gareth_bowles
Er, *bash* is the “Bourne again shell”. *sh* is commonly a link to some other shell like *dash* (Debian Almquist shell) or *bash* (though *sh* is actually the Bourne shell on (e.g.) Solaris).
Chris Johnsen
Edited based on Chris' comment - thanks, I stand corrected.
gareth_bowles
A: 

Maybe you can find a solution on www.commandlinefu.com there is a lot of Unix commands

ElAlecs
A: 

You can omit the shebang if you run the script from a shell, in that case the contents will be executed by your current shell instance. In many cases this will cause no problems, but it is still a bad practice.

wRAR
It depends on how you run the script. If you say `sh /path/to/script`, then the shbang is not needed. If you say `/path/to/script`, then it is best to include a shebang, even if you are only running it from another shell.
Chris Johnsen