I am trying to execute specific line of text file in bash. I was wondering is it possible to do that without copying that line in a new file and executing it?


Building on @kev's answer (without piping to a new bash): Take his script source


echo hello
echo world
echo foo
echo bar

and execute a certain line inside a $(...):


$(sed -n '3p' script.sh)

It will print foo in bash your current shell.

  • @ormaaj: I agree with you in discouraging such a concept. On the other hand it comes handy when following instructions from a simple diary (log) file. – fheub Jul 13 '12 at 9:49
  • I agree, this is exactly why am I using it. – Vladimir Perković Jul 13 '12 at 9:55
  • 1
    @fheub: This isn't a good answer because the argument list is built by word-splitting, with pathname expansion enabled. This will fail in all but simple cases. Always quote command substitutions. kev's answer is ok. Mine works in either a child process or the current environment because of the eval (and uses properly escaped input). If you have GNU sed available, a shell command can be executed in pure sed using the e function: sed -n $'3{e\np;q}' file – ormaaj Jul 13 '12 at 10:15
  • @ormaaj: Touché! But Vladimir seems to be looking for a KISS-solution. – fheub Jul 13 '12 at 10:27


echo hello
echo world
echo foo
echo bar


sed -n '3p' script.sh | bash

It will print foo

  • I think you should pipe to bash as Vladimir wants to execute the line. – Bernhard Jul 13 '12 at 7:27

If you are talking about a shell script, you could do that like in this example:

LINE="$LINE myfile.txt"
# now we execute that:

Another example includes capturing the output for further processing:

LINE="grep foo bar.txt"

In the second example, the variable $OUTPUT then contains the results of the executed grep command.


Probably not quite what you want, but could be useful to mention:

history -r script.sh

This reads each line of the script into your history list, from which you can execute any line using bash's history expansion feature.

A few failed attempts at reading in just the line you want to execute:

# No command substitution; the argument is added literally
history -s $(sed -n '3p' script.sh)

# Can't seem to read from stdin or from a process substitution
sed -n '3p' script.sh | history -r -
sed -n '3p' script.sh | history -r /dev/stdin
history -r <( sed -n '3p' script.sh )

You could but probably shouldn't. Create a library containing functions and source it. This is a very unusual requirement. Bash has actual means of control flow - there's no need to grab strings of code out of files to execute. This can be dangerous.

Here's a "toy" example, not for production use...

#!/usr/bin/env bash

shopt -s extglob

# evalLine filepath line-number
evalLine() {
    [[ -f $1 && $2 == +([[:digit:]]) ]] || return 1
    local x
    # This subtraction compensates for a bug that's since been fixed in 4.2.35 
    mapfile -ts $(($2 - 1)) -n 1 x &&
    ${x:+eval "$x"}
} <"$1"

evalLine /dev/stdin "$1" <<"EOF"
echo "line 1"
f() { echo "$1"; }; f "line 2"
var3='line 3' eval 'echo "$var3"'

Late edit: Note the comment regarding a bug in mapfile.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.