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?
2 Answers 2
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– fpmurphy2017年03月15日 00:47:02 +00:00Commented Mar 15, 2017 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– ilkkachu2017年03月17日 15:18:18 +00:00Commented Mar 17, 2017 at 15:18
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– XZS2017年03月23日 19:49:01 +00:00Commented Mar 23, 2017 at 19:49
You must log in to answer this question.
Explore related questions
See similar questions with these tags.
touch file; chmod u+x file; dostuff >> file; ./file
?chmod
step?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./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.