eval used with piped command

eval does not read its command string from stdin.

eval "$(cat file.txt)"
# or easier, in ksh/bash/zsh
eval "$(<file.txt)"
# usually you cannot be sure that a command ends at the end of line 5
eval "$(head -n 5 file.txt)"

Instead of eval you can use standard . or bash/zsh/ksh source if the commands are in a file anyway:

source ./file

(note that it's important to add that ./. Otherwise source looks for file in $PATH before considering the file in the current directory. If in POSIX mode, bash would not even consider the file in the current directory, even if not found in $PATH).

That does not work with choosing a part of the file, of course. That could be done by:

head -n 5 file.txt >commands.tmp
source ./commands.tmp

Or (with ksh93, zsh, bash):

source <(head -n 5 file.txt)

so... a solution to your question is 100% possible, and (in the context of make) important.

I ran into this with a makefile, and given the difficulty of nesting bash commands in a makefile which already uses $(...) to call variables, it is nice to be able to do exactly what you are asking about.

Rather than using eval, just use awk or perl's system command:

// command_list.sh:
echo "1"
echo "2"
echo "3"

// command line prompt:
$: cat command_list.sh | awk '{system($0)}'
1
2 
3

And, command building:

// a readable version--rather than building up an awk miniprogram, 
// split into logical blocks:

$: cat inputs.txt | awk '{print "building "$1" command "$2" here "}' | awk '{system($0)}' 

Tags:

Bash

Pipe