5

Consider you have a file with some sort of terminal command. How might each line be executed? Can you pipe the output of more into an eval?

%> more ./foo.txt

Edit:

After some help/guidance from the comments, I think I should also make note that it's been a while since I've done any shell scripting, so while I say eval I may mean echo or some other way of executing code.

If foo.txt contains various lines of code, but I want to execute the line that contains echo 'bar bar', I'm looking for a way to do that from, let's say a grep. Something logically similar to:

grep echo foo.txt | xargs echo
vol7ron
  • 465
  • 1
  • 7
  • 14

1 Answers1

8

If you just need to evaluate every line of a file, you don't need a complicated eval or stdout redirection. Two easy options:

  • Source the file (source filename.sh or . filename.sh).
  • Make the file executable and run it (chmod +x filename.sh; ./filename.sh)

If you really need to eval each line of a file in a loop, do it with while:

while IFS= read -r line; do eval "$line"; done < filename.sh

You can also pipe the output of any command to while:

grep foo filename.sh | while IFS= read -r line; do eval "$line"; done

If you need to pass something to source (or .), which expects a file name as an argument, you can use process substitution:

source <( grep foo filename.sh )
slhck
  • 223,558
  • 70
  • 607
  • 592
  • I like, but is there a way to do this w/o using `bash`? I know I tagged it, so I'm just curious, since I don't always use it. – vol7ron Apr 15 '13 at 14:38
  • `source` isn't Bash-specific and should work in most other shells (Bourne Shell, (t)csh) as well. – slhck Apr 15 '13 at 14:48
  • Right now, `source` would work but I like to think ahead in the case that there are lines I wan't to strip out and possibly use the output of `grep` – vol7ron Apr 15 '13 at 14:59
  • 2
    Technically, `source` is a non-standard synonym for `.`. – chepner Apr 15 '13 at 15:08
  • @chepner: right, but can you pump `more`/`grep` into an `eval` (guessing `echo`) from the terminal command line? Perhaps into `find -exec`? – vol7ron Apr 15 '13 at 17:27
  • @vol7ron: You cannot pipe into `eval`, since it does not read from standard input. It takes a string as an argument. That said, why do you think you need to use `eval`? It's rarely necessary. – chepner Apr 15 '13 at 17:29
  • @chepner not saying I do - been a while since I've done any shell scripting. I may need to edit the question, instead of posting this as a comment, but I'm looking to execute specific lines from a file (eg output of `grep string_match foo.txt`) I figured I'd have to pipe that into `echo` or `eval` – vol7ron Apr 15 '13 at 17:36
  • @vol7ron You can use process substitution to pass the output of a list of commands to `source`, or pipe the output from your scripts to `while`. – slhck Apr 15 '13 at 17:42
  • @slhck don't get me wrong the `while` worked in Bash, I was looking for something that may be shell independent, which again, I asked too open of a question so it's entirely my fault. The `source` I think would work, just isn't as descriptive when I go back to read what I did a couple years from now :) – vol7ron Apr 15 '13 at 17:45
  • @vol7ron `while` for reading each line and process substitution is also supported in Zsh and ksh. You can use `while` in the Bourne Shell as well, so this is as portable as you can get AFAIK. (t)csh uses completely different syntax, so you won't get far with that I'm afraid. – slhck Apr 15 '13 at 17:53
  • @slhck and that's the rub :( – vol7ron Apr 15 '13 at 17:54
  • @vol7ron Not pretty, but you can always use a temporary file and source that of course. – slhck Apr 15 '13 at 18:32
  • @slhck thanks for continuing to think on this, I'd rather force the use of `bash` than to go that route, but it's an interesting idea. – vol7ron Apr 15 '13 at 18:40