[Techtalk] re: Joining commands together in bash

Malcolm Tredinnick malcolm at commsecure.com.au
Mon May 12 22:00:10 EST 2003


On Mon, May 12, 2003 at 03:25:23AM -0700, Berenice wrote:
> This is great.  So now I've learned 2 new things about bash.

Cool. :-)

I may be flogging an already bolted horse here, but a couple of
comments:

> On Sun, May 11, 2003 at 12:34:07PM +0100, Meredydd wrote:
> > This is how I would do it:
> > 
> > for FILE in * ; do
> >   if [ x`file $FILE | grep 'shell script text executable'` != x ]; 
> > then
> >    head -n 3 $FILE
> >   fi
> > done

Note that adding a preventative character before the backtick is not
just to protect against empty strings in older shells (although that is
a good reason).  It also stops strange things happening is the result of
the subshell command begins with a hyphen (the subshell command here is
the "file $FILE ..." bit). The '[' part of the line above is actually a
synonym for the 'test' command and if you look at "man test", you see
that there are a number of options that can be passed to test. So if the
result of the `...` portion came out to be "-dog" (say), things would
start to go wrong. Adding an initial non-hyphen character prevents this
(because now you are running test aginsts "x-dog" and comparing it to
"x"). These days, that is the reason people use that option, since the
old shells are mostly gone (but I had to fix a bug report in GNOME the
other day that was due to one of those shells, so they are still
around), but filenames beginning with a hyphen can still exist, even if
just by accident.

> Do newer versions of bash accept statements in the form of
> x`blahblah` != x  ?

I ma not sure exactly what you are typing, byt the blahblah bit has to
be something that can be executed by a shell, since it is run in a
subshell.

> I know you've said it works in older shells, but it doesn't seem to
> work in mine. I don't know if I'm typing it wrong, but I also tried
> `echo hi` at the command prompt and got the message "bash: hi: command
> not found".  Just wondering...

The backticks are what are biting you here: The shell executes the thing
inside the backticks (so you get "hi") and then attempts to run whataver
is on the command line after that substitution. That is, it is trying to
run the command "hi", which does not exist.

Compare the result of 

	echo ls

with the result of

	`echo ls`

The first one executes the "echo" command and behaves as you would
expect. The second one executes the echo command in a subshell (caused
by the backticks) and then executes what is left (the resulting "ls") in
the main shell, giving you a directory listing.

> Date: Sun, 11 May 2003 21:46:52 +1000
> From: Malcolm Tredinnick <malcolm at commsecure.com.au>
> 
> >Straight out of the "more than one way to skin a cat" bucket, here
> is 
> >my solution:
> 
> >file * | grep 'shell script text executable' | cut -f1 -d':' | xargs
> 
> >head -n 3
> 
> This is the first time I've seen the xargs command. It's quite handy!

By the way, I realised later that my solution did not solve your problem
exactly as written -- it still displays the filenames. If you do not
want the filenames and just want the first three lines, then the very
last part should be "xargs --max-args 1 head -n 3".

Also both Meredydd's and my solutions fail on filenames with spaces in
them. Meredydd's version can be fixed, but I think my one requires some
trickery with xargs that I cannot think of for the moment.

Cheers,
Malcolm

-- 
Save the whales. Collect the whole set.


More information about the Techtalk mailing list