Answers to: Passing a stream to a bash functionhttp://linuxexchange.org/questions/3098/passing-a-stream-to-a-bash-function<p>Hello I have a problem, I need to create a BASH function that I can pass a stream to NOT A FILE. Here is the function: function ff() { cat /etc/group | fgrep -f "$1" }; When I run it like so</p> <pre><code>ff &lt;( echo some_user ) </code></pre> <p>I get an error saying "fgrep: /dev/fd/63: No such file or directory", instead of "some_uer:x:0:"</p> <p>Much Appreciated!</p>enFri, 07 Jun 2013 17:53:46 -0400Answer by josephj11http://linuxexchange.org/questions/3098/passing-a-stream-to-a-bash-function/3116<p>I don't have enough points to edit or comment here, so:</p> <p>Your primary problem is that, in a function, $1 refers to the first argument passed to the function, <em>not</em> to the the first argument passed to the calling script. You don't pass any arguments to your function, so $1 should be undefined or a null string - not what you wanted. If you run your script using <code>bash -vx script-file arguments</code>, then you'll see how bash is interpreting it.</p> <p>For how to actually fix it, see <a href="/users/1702/kj4tip">@KJ4TIP</a> 's answer.</p>josephj11Fri, 07 Jun 2013 17:53:46 -0400http://linuxexchange.org/questions/3098/passing-a-stream-to-a-bash-function/3116Answer by modhttp://linuxexchange.org/questions/3098/passing-a-stream-to-a-bash-function/3104<p>OK, this is the solution, based on process substitution and fgrep's -f flag:</p> <pre><code>function ff() { fgrep &lt; /etc/group -f $1 ; } ff &lt;( echo some_user ) </code></pre>modWed, 15 May 2013 08:55:03 -0400http://linuxexchange.org/questions/3098/passing-a-stream-to-a-bash-function/3104Answer by shamilbihttp://linuxexchange.org/questions/3098/passing-a-stream-to-a-bash-function/3103<p>function ff() { read name; fgrep "$name" &lt; /etc/group ; }; echo "user"| ff</p>shamilbiWed, 15 May 2013 08:46:07 -0400http://linuxexchange.org/questions/3098/passing-a-stream-to-a-bash-function/3103Comment by KJ4TIP on mod's answerhttp://linuxexchange.org/questions/3098/passing-a-stream-to-a-bash-function#3102<p>But note that the <code>-f</code> flag makes <code>grep</code> expect the name of a file containing patterns, not a pattern itself. Also, since <code>grep</code> cat take names of files to search after the pattern file, the input redirection is unnecessary.</p>KJ4TIPWed, 15 May 2013 08:41:41 -0400http://linuxexchange.org/questions/3098/passing-a-stream-to-a-bash-function#3102Answer by modhttp://linuxexchange.org/questions/3098/passing-a-stream-to-a-bash-function/3101<p>First of all (a pet peeve) let's get rid of the unnecessary invocation of cat in your function:</p> <pre><code>function ff() { fgrep "$1" &lt; /etc/group ; } </code></pre> <p>Next, be aware that your use of that '&lt;()' notation invokes what's called "process substitution" which executes a pipeline in a separate process and associates its stdout with a file created for the purpose; any such expression evaluates to the <strong>name</strong> of that file, so the error message you're seeing is correct.</p> <p>In other words, you've presented the <strong>name</strong> of the pipeline's stdout file when what you wanted was the <strong>contents</strong>, almost as if you'd done this:</p> <pre><code>echo some_user &gt; myTempFile ff myTempFile </code></pre> <p>...so you may by now see that in your case you could get what you want (if a bit awkwardly) thus:</p> <pre><code>ff $(cat &lt;( echo some_user ) ) # cat is necessary here ;-&gt; </code></pre> <p>...which, of course, makes it tempting to then do away with the process substitution trickery and simply do this:</p> <pre><code>ff $(echo some_user) </code></pre> <p>Bash's process substitution facility is way cool but maybe overkill here...</p>modWed, 15 May 2013 08:27:42 -0400http://linuxexchange.org/questions/3098/passing-a-stream-to-a-bash-function/3101Answer by KJ4TIPhttp://linuxexchange.org/questions/3098/passing-a-stream-to-a-bash-function/3099<p>It appears that bash is closing the stream before grep gets a chance to open it; it could be caused by grep not being the first command in the pipeline. Try</p> <pre><code>function ff() { fgrep -f "$1" /etc/group; } </code></pre> <p>EDIT: Rather than the stream being closed prematurely, it appears that the way bash handles this is by connecting an unnamed pipe between <code>&lt;(echo user)</code> and the first command in the pipeline, namely <code>cat</code> in your case, and then giving the command a filename of the form <code>/dev/fd/</code><em>n</em>, where <em>n</em> is the number of the file descriptor of the pipe, in your case 63. The problem occurs because the file descriptor is not duplicated to the other commands in the pipeline, so <code>cat</code> has access to the stream but <code>grep</code> does not. The remedy is either to move the command that needs access to the stream to the beginning of the pipeline, as above, or, in the event that is not possible, to explicitly use named pipes, e.g.</p> <pre><code>mkfifo pipe echo user &gt;pipe &amp; ff pipe rm pipe </code></pre>KJ4TIPMon, 13 May 2013 20:19:02 -0400http://linuxexchange.org/questions/3098/passing-a-stream-to-a-bash-function/3099