Updated: 22 October 2026 · Applies to: bash 5.3 on Ubuntu 26.04 LTS and bash 5.1 on AlmaLinux 9; the same syntax works in bash on any Linux distribution
Input redirection feeds a file, or text you type in the script, to a command’s standard input instead of the keyboard. command < file reads from a file, command <<EOF reads the lines that follow until EOF (a here document), and command <<< "text" reads one string (a here string).
stdin, stdout and stderr
Every command starts with three open channels, each with a number called a file descriptor:
- 0, standard input (stdin): where the command reads from. Normally the keyboard.
- 1, standard output (stdout): normal output. Normally the screen.
- 2, standard error (stderr): error messages. Also the screen.
Input redirection changes descriptor 0. For the output side (>, >>, 2>, 2>&1), see redirecting command output.
1. Read from a file with <
$ wc -l fruit.txt 3 fruit.txt $ wc -l < fruit.txt 3
With <, the shell opens the file and wc only sees a stream of text, so it prints no file name. That is handy in scripts where you want just the number.
You can combine input and output redirection in one command:
sort < fruit.txt > sorted.txt
The everyday server example is importing a database dump: mysql shopdb < backup.sql sends the SQL file to the client as if you had typed it (see dumping and importing MySQL or MariaDB databases). The same works for SQLite: sqlite3 test.db < dump.sql.
If the file does not exist, the command never runs and bash reports:
bash: nofile.txt: No such file or directory
2. Read a file line by line
while read -r line; do
echo "Fruit: $line"
done < fruit.txt
Fruit: banana Fruit: apple Fruit: cherry
The < fruit.txt after done feeds the whole loop. -r stops read from treating backslashes as escape characters.
3. Here documents (<<)
A here document sends several lines written in the script itself. It is the usual way to write a config file from a script:
name=web01 cat <<EOF Server: $name User: $(whoami) EOF
Server: web01 User: root
Variables and commands are expanded. Put the first delimiter in quotes to keep the text exactly as written, which is what you want for config files full of $ signs:
cat > /tmp/site.conf <<'EOF' server_name example.com; root /var/www/example; EOF
With <<'EOF', a line such as Server: $name stays exactly Server: $name. With <<-EOF, bash removes leading tab characters (not spaces) from each line and from the closing EOF, so you can indent the block inside an if or a function. The closing word must be alone on its line.
4. Here strings (<<<)
A here string sends one line, followed by a newline:
$ tr a-z A-Z <<< "hello $name" HELLO WEB01 $ read -r first second <<< "alpha beta"; echo "$first / $second" alpha / beta
This also avoids a classic pipe trap. The bash manual explains that each part of a pipeline runs in its own subshell, so a variable set by read at the end of a pipe disappears:
$ echo "hello" | read -r x; echo "x=[$x]" x=[] $ read -r y <<< "hello"; echo "y=[$y]" y=[hello]
5. Other file descriptors and process substitution
You can open a file on another descriptor and read from it step by step:
exec 3< fruit.txt # open fruit.txt as descriptor 3 read -r a <&3 # first line read -r b <&3 # second line exec 3<&- # close descriptor 3 echo "$a $b" # banana apple
Process substitution, <(command), lets a command read another command’s output as if it were a file. For example, compare two lists after sorting them, without temporary files:
diff <(sort list1.txt) <(sort list2.txt)
Redirection and sudo
Your own shell opens the file, before sudo starts. So this fails for a normal user even though the command runs as root:
$ sudo wc -l < /etc/shadow bash: /etc/shadow: Permission denied
Let the root command open the file instead: sudo wc -l /etc/shadow, or sudo sh -c 'wc -l < /etc/shadow'. The same applies to output: sudo echo text > /etc/file fails for the same reason.
Quick reference
cmd < file: read stdin from a file.cmd <<EOF...EOF: here document, with expansion.cmd <<'EOF': here document, text kept literally.cmd <<-EOF: here document, leading tabs removed.cmd <<< "text": here string.cmd <&3: read from descriptor 3;exec 3<&-closes it.cmd <(other): read another command’s output as a file.
Official documentation: GNU bash manual: Redirections.