1. Overview
The echo command is designed to display text passed as arguments. So, it’s not a common practice to use echo for displaying content from a file. Moreover, utilities, such as cat, less, and so on, conveniently show content from a file.
Nevertheless, there could also be many acceptable scenarios, such as educational demos, displaying file content with additional information, etc.
In this tutorial, we’ll learn multiple ways to redirect the contents of a file to the echo command.
2. Understanding the Scenario
Let’s imagine that we’ve got some textual content in the data.txt file:
$ cat data.txt
line-1
line-2
Now, our goal is to show content from the file along with an extra line of text:
line-1
line-2
end-of-file
Moreover, we might want to perform this task repeatedly. So, we should see if we can keep the calls to I/O utilities minimal.
Lastly, let’s see a common mistake that we could make while solving this use case:
$ cat data.txt | echo
We may expect that since we’ve piped the output of the cat command to echo, it should display the content. Unfortunately, we don’t see any output on the console because the pipe connects the output of the first process to the input of the second process. However, echo uses its argument instead of stdin for displaying text.
3. Using Command Substitution
The echo command can only show text that’s passed as an argument. So, we need to read the contents from the data.txt file separately and then pass that as the first argument to echo.
In this section, we’ll learn how to use command substitution to redirect content from a file to echo.
3.1. With cat
Let’s see how we can use command substitution to send the content of the data.txt file as an argument to echo:
$ echo -e "$(cat data.txt)" "\nend-of-file"
line-1
line-2
end-of-file
We must note that we’ve used the -e flag to enable the interpretation of backslash escapes. As a result, we can add a newline character (\n) as part of the second argument.
3.2. With $(< file)
We can replace the $(cat data.txt) command substitution with $(<data.txt). Further, it’s worth noting that the latter is much faster because it doesn’t need to create a subshell process. As a result, using the latter approach over the former is almost always recommended.
Now, let’s rewrite our code using this approach and verify its functionality:
$ echo -e "$(<data.txt)" "\nend-of-file"
line-1
line-2
end-of-file
Perfect! It works as expected.
4. Using sed
sed is one of the commonly used text-processing utilities that we can use to solve our use case. Notably, sed processes the file as a stream of lines, so we must consider passing each line to the echo command separately.
Let’s see how we can use the substitution (s) command to pass each line as an argument to the echo command:
$ sed -n -e 's/.*/echo &/ep' data.txt && echo "end-of-file"
line-1
line-2
end-of-file
We’ve got the correct results. Further, we must note that we used the /e flag for sed to execute the echo command.
5. Using awk
Alternatively, we can use awk to read the contents from the data.txt file and then pass it to the echo command. Like sed, awk also processes the file sequentially, one line at a time. So, we’ll pass each line as an argument to echo individually.
Now, let’s see how we can write an awk script to redirect the content from the data.txt file to the echo command:
$ awk \
'{
system("echo " $0);
}
END {
system("echo end-of-file");
}' data.txt
line-1
line-2
end-of-file
It’s important to note that we’ve called the system() function to execute the echo command from within the awk script. Additionally, we use the END block to display “end-of-file” text because we need it only once after processing the entire file.
6. Using while Loop With read
In this section, let’s explore an iterative approach using a while loop to read the content from the data.txt file line-by-line. So, we can conveniently pass a single line to echo in each iteration.
Let’s write our iterative solution that uses < for input redirection:
$ while read line;
do
echo "$line";
done < data.txt
echo "end-of-file"
line-1
line-2
end-of-file
Fantastic! We’ve nailed this one!
7. Using xargs
In this section, we’ll learn how to use the xargs command to solve our use case of redirecting the content of the data.txt to the echo command.
7.1. With Input Redirection
We can use xargs with the -L1 option to read one line at a time from data.txt and execute echo with each argument:
$ xargs -L1 echo < data.txt && echo "end-of-file"
line-1
line-2
end-of-file
Alternatively, we can use the -I option with {} placeholder, and xargs replaces the {} argument for echo with the actual input:
$ xargs -I{} echo {} < data.txt && echo "end-of-file"
line-1
line-2
end-of-file
That’s it! It looks pretty convenient.
7.2. With fold
Sometimes, we might want to preprocess the file’s content before passing it to the echo command. One interesting scenario is where we want to wrap long lines to a fixed length before displaying them.
Let’s understand this with the help of a sample file named digits.txt:
$ cat digits.txt
0123456789
We can see that the file contains all digits in a single line. Our goal is to redirect this file’s contents to echo so that it shows one digit per line.
To solve this use case, we can use the fold command with the –width=1 option and then pipe it with the xargs command:
$ fold --width=1 digits.txt | xargs -L1 echo; \
echo “end-of-file”
0
1
2
3
4
5
6
7
8
9
end-of-file
Great! The output looks correct.
7.3. With fmt
Let’s imagine that we’ve got whitespace separating each digit from 0 to 9:
$ cat digits_with_space.txt
0 1 2 3 4 5 6 7 9
Next, let’s apply the fold command to such a file to redirect to the echo command later on:
$ fold --width=1 digits_with_space.txt; \
echo “end-of-file”
0
1
2
3
4
5
6
7
9
end-of-file
Unfortunately, this doesn’t work well as we have an extra blank line between two digits.
To solve such an issue, we can use the fmt command and specify the width as 1:
$ fmt --width=1 digits_with_space.txt | xargs -L1 echo; \
echo “end-of-file”
0
1
2
3
4
5
6
7
9
end-of-file
Perfect! fmt works well for such a scenario. Furthermore, we must note that we’ve piped the output of fmt to xargs for redirecting the content to echo.
8. Using parallel
In this section, let’s learn how to use the parallel utility for solving our use case.
First, let’s install the parallel package using apt-get as it’s not preinstalled:
$ sudo apt-get install parallel -y
Next, let’s go ahead and use parallel with the -k flag to redirect the contents of data.txt to echo:
$ parallel -j1 -k echo ::: <data.txt && echo "end-of-file"
line-1
line-2
end-of-file
We can note that we used the ::: delimiter to separate the command from its arguments. Further, the arguments are built by redirection from the data.txt file.
Lastly, it’s important to note that using -j1 and -k flags preserves the order by keeping the number of jobs to 1. If we’ve got a use case where the order isn’t that important, we can increase the number of jobs and make it faster.
9. Conclusion
In this article, we learned how to redirect the content of a file to the echo command. We started with the concept of command substitution and used the cat command to pass the file’s content to echo.
Furthermore, we explored several other command-line utilities, such as sed, awk, xargs, read, parallel, and so on, to solve the use case at hand.