42

Previously I used source command like this:

source file_name

But what I'm trying to do is this:

echo something | source

Which doesn't work.

Braiam
  • 35,991
Desmond Hume
  • 2,798

2 Answers2

70

Since source (or .) takes a file as argument, you could try process substitution:

source <(echo something)
nnnmmm
  • 155
muru
  • 72,889
11

Your source command requires a file argument. You can get that in some shells with a process substitution, and this is because in the same way the shell replaces...

arg=$(echo hi)

...the echo bit there on the command-line with the subshell's output, in the case of process substitution it replaces the subshell with a named file - usually /dev/fd/62 or something - some link to a file-descriptor. With a pipe the file descriptor is 0 so...

echo 'echo hi' | . /dev/fd/0

... /dev/stdin or whatever as the case may be should work just fine on any linux system - and many others besides. You can also use here-documents similarly:

. /dev/fd/3 3<<HI
$(echo 'echo hi')
HI

You can verify the way your shell handles process substitution, by the way:

(set -x; readlink <(:))

...which prints (in bash):

+ set +x
+ readlink /dev/fd/63
++ :
pipe:[2212581]

...and so we can see that the shell is doing the substitution and readlink is reading from an an anoymous pipe that it opens on file-descriptor 63.

mikeserv
  • 58,310
  • 1
    You cannot use a process in a pipe (your example echo 'echo hi' | . /dev/fd/0) to make side-effects in the current shell (like setting aliases, environment etc.) because the commands in a pipe are run as child processes and their side-effect are lost when they are finished. – pabouk - Ukraine stay strong Mar 29 '22 at 07:20