2

Using pipes, one can create files with simple shell built-ins.

{ echo "#!/bin/bash" \
  echo "echo Hello, World!" \
} > helloworld.sh

With chmod these can then be made executable.

$ chmod 755 helloworld.sh
$ ./helloworld.sh
Hello, World!

I wonder whether it is possible to save the chmod step. Already, I found that umask cannot do the job. But perhaps someone knows an environment variable, bash trick, program to pipe through or other neat way to do it.

Is it possible to have the file created with the executable bit already set?

  • Have you tried touch file; chmod u+x file; dostuff >> file; ./file? – DopeGhoti Mar 14 '17 at 20:14
  • why do you want to skip the chmod step? – schaiba Mar 14 '17 at 20:17
  • The purpose to skip chmod is to reduce changes to a single point. When the file name or path should later change, the change would than only affect this single line. Defining a variable keeping it would be an alternative, but add an otherwise unnecessary line. – XZS Mar 14 '17 at 20:32
  • 2
    you're already using the filename twice (creation, execution); a variable seems reasonable to me. – Jeff Schaller Mar 14 '17 at 20:37
  • I often see this situation in packaging software for Linux distributions. A small wrapper start script around an executable (for example in /opt) has to be created via pipe, then made executable, which makes exactly these two uses. The one who calls the script then, is the user who installed the package. – XZS Mar 14 '17 at 20:44
3

It is not possible to create an executable file solely with a shell redirection operator. There is no portable way, and there is no way in bash either (in the source code, you can see that redirection calls do_redirection_internal which calls redir_open with the parameter mode set to 0666, and this in turn calls open with this mode).

You're calling a shell command anyway, so add ; chmod +x … somewhere in it. There's absolutely nothing wrong with that. One more line of code is not a problem. You need to do three things (create a file with some given content, make the file executable, execute it), so write three lines.

There is a relatively obscure shell command that can create an executable file with some specified content: uudecode. But I would not recommend using it: it requires the input to be passed in a non-readable format, it bypasses the user's umask, and it's obscure.

A sane alternative is to call bash /the/script instead of chmod +x /the/script && chmod +x, if you know what interpreter to execute the file with.

  • The uudecode utility is not "relatively obscure" or "obscure". Been around in distributions since BSD 4.0 and is still used by many. – fpmurphy Mar 15 '17 at 0:47
  • @fpmurphy1, I think it's safe to say it's "relative obscure" nowadays, with MIME used on email, and proper news servers quite rare. – ilkkachu Mar 17 '17 at 15:18
2

A function to create an executable shell script from piped input:

pipe2script() { touch "$1" ; chmod +x "$1" ; \
                echo '#!'"$(which ${2:-bash})"  > "$1" ; cat >> "$1" ; }

Use pipe2script to pipe two lines of text to foo.sh:

printf 'echo hello world\necho bye\n' | pipe2script foo.sh

This outputs a new executable file, foo.sh:

$ ls -log foo.sh 
-rwxrwxr-x 1 38 Mar 18 09:05 foo.sh

Running cat foo.sh shows:

#!/bin/bash
echo hello world
echo bye

Run it:

./foo.sh

Output:

hello world
bye

The pipe2script function defaults to using bash, but it can take a second argument of any other shell name, i.e. dash, zsh, ksh93, python, etc. Example using the fish shell's math command:

printf 'math "99^33"\n' | pipe2script foo.fish fish

Running cat foo.fish shows:

#!/usr/bin/fish
math "99^33"

Output of ./foo.fish:

717730532598275105894510914059816191752829524684539601273450723299

Edit a copy of a script:

sed '2,${s/.*/echo & | jethro/e;s/ / "/;s/$/"/}' foo.sh | pipe2script foojc.sh

Output when run:

$ ./foojc.sh 
howdy world
y'all come back now, heah?
  • I chose Gilles' answer as the "correct" one as it provides a method that works within one single pipe, which was the "trick" I sought. This answer is very useful nonetheless and would be the one with more practical use. – XZS Mar 23 '17 at 19:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.