0

I'm trying to run a program with each of my script's arguments passed as a different line on stdin. My current attempt involves using a for loop, as follows:

#!/bin/bash

[My Program] <<EOF
for i in "$@"
do
   $i
done

EOF

This doesn't work -- the program actually receives for i in as part of its input, instead of being given the list of arguments themselves. How would I change it to function?

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
Leo Choi
  • 9
  • 3
  • 2
    What's this `run` command that (presumably) takes a script on its input? Where are you getting it from? Where's its documentation? If you want to defer the evaluations of the heredoc's contents you need to quote the sigil (`<<'EOF'` rather than `< – Charles Duffy Feb 12 '18 at 01:56
  • 1
    If you just want to count arguments, `count=$#` and there you are. No loop needed, no heredoc, no nonexistent `run` command. – Charles Duffy Feb 12 '18 at 01:58
  • 2
    If you want to clarify a specific question here, please try to build a [mcve] -- the simplest possible code that generates your problem, with examples of input/invocation, intended output, and actual output. – Charles Duffy Feb 12 '18 at 02:00
  • The run is a program made with C. Actually, It doesn't matter. The problem is that I can't specify EOF state by using for state... – Leo Choi Feb 12 '18 at 02:01
  • Here is a similar question: https://stackoverflow.com/questions/38780931/loop-inside-heredoc-in-shell-scripting – z atef Feb 12 '18 at 02:09
  • 1
    What do you mean by the words "EOF state"? What you create with `< – Charles Duffy Feb 12 '18 at 02:10
  • I've edited the question to be less confusing. Of course, that assumes that I interpreted it correctly -- if not, please roll the edit back and replace with similarly unambiguous text asking whatever you actually meant. – Charles Duffy Feb 12 '18 at 02:18
  • BTW, you could just run `printf '%s\n' "$@" | ./run` and skip the heredoc altogether. – Charles Duffy Feb 12 '18 at 02:28

1 Answers1

1

To feed your program's stdin a newline-separated list of the command-line arguments with which your script was called:

#!/usr/bin/env bash
./your-program <<<"$(printf '%s\n' "$@")"

...or, with POSIX sh-compatible heredoc syntax:

#!/bin/sh
./your-program <<EOF
$(printf '%s\n' "$@")
EOF

If for some reason you really want to use a for loop, you can do that:

#!/bin/sh
./your-program <<EOF
$(for i; do
    echo "$i"
  done)
EOF

...though note that printf would be a preferable replacement to echo even here; to understand why, see the APPLICATION USAGE section of the POSIX spec for echo.

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • Does the program see anything different than with `./your-program "$@"`? I assume that the newlines in your solution are eliminated anyway during word-splitting of the `printf` result, but I may be wrong. – Peter - Reinstate Monica Feb 12 '18 at 08:49
  • @PeterA.Schneider, inside a heredoc there is no word-splitting. And because this is *inside a heredoc*, the contents are on stdin, not on the command line (which AFAICT is what the OP was asking us how to do). – Charles Duffy Feb 12 '18 at 14:23