Shell Scripting: Using grep and tr in the shebang
Asked Answered
S

1

5

I have this script on my system:

#! /bin/grep cat

caterpillar
cat
lol
morecat

When I run it, I get the output as expected,

#! /bin/grep cat
caterpillar
cat
morecat

But, if I use tr instead, with the script

#! /usr/bin/tr 'a' 'e'

caterpillar
cat
lol
morecat

I expect to get

#! /usr/bin/tr 'a' 'e'

ceterpiller
cet
lol
morecet

But instead nothing is printed, and if I manually type cat, I get c/t. How can the script be changed to behave like the first?

Sickler answered 15/3, 2014 at 20:29 Comment(1)
Because grep takes a file argument, but tr does not.Tavel
O
9

The shebang line only supports a single argument. Spaces are included literally and there is no quoting. So the command you're running there is equivalent to this from a shell:

tr "'a' 'e'"

If you run that you'll see that tr complains about the lack of a second argument. So why does your script not complain? Well that's the second problem. shebang cat or grep works because cat and grep takes name of an input file as an argument, and the shebang adds the script's name to the argument list. (That's required for the basic case of a #!/bin/sh script to be executed as /bin/sh scriptname)

You are therefore running

tr "'a' 'e'" yourscriptname

which gives tr the 2 arguments it needs, and it then reads from stdin, translating from a set of characters you didn't intend to another set of characters you didn't intend.

If the shebang line had a fully functional shell parser, you could use

#!/usr/bin/tr 'a' 'e' <

And the filename added to the end would become the input. But shebang is just a simple thing in the kernel, not so featureful.

Osborn answered 15/3, 2014 at 20:41 Comment(1)
Thanks! That would also explain why "#! /bin/bash cat" is printed as well.Sickler

© 2022 - 2024 — McMap. All rights reserved.