1

Introduction

I was trying to do some instructions on a file line by line with:

while IFS= read -r line; do
    ...
done < file

When I noticed that there was a problem with trailing whitespaces (for example: " a " => "a") that were automatically deleted, which is a real problem for me.

I searched in the documentation and didn't find any mention of that. And there is the same problem with printf.

Minimal example:

touch example # Create a file
echo "  exa    mple    " >> example # Add some text
cat example #    exa    mple    
echo $(cat example) # exa mple
rm example # Delete the file

In this example, I don't understand why echo $(cat example) doesn't have some trailing whitespaces.

And this "problem" is also here with:

while IFS= read -r line; do
    echo $line # exa mple
done < example

Version:

Tested with:

  • zsh v5.9
  • bash v5.2.2
Cyrus
  • 84,225
  • 14
  • 89
  • 153
TKirishima
  • 742
  • 6
  • 18
  • Remove `IFS=` from `IFS= read -r line` to allow leading/trailing spaces and tabs to be removed. With `IFS=`, you're specifying "there are no word splitting characters" which allows the line to be captured verbatim. The unquoted `echo $(cat example)` allows word splitting to occur. – glenn jackman Dec 05 '22 at 16:05
  • @glennjackman Are you sure for the `IFS=` ? If yes can you provide a code example that works? I tested your suggestion on the problem that I mentioned and didn't notice any differences – TKirishima Dec 05 '22 at 16:11
  • The result of unquoted `$(cat example)` is subject to word splitting. Try with `echo "$(cat example)"`. But this is "Useless Use of echo" – M. Nejat Aydin Dec 05 '22 at 16:12
  • Oh @M.NejatAydin looks like you're right ok! – TKirishima Dec 05 '22 at 16:14
  • @TKirishima, I lost track of whether or no you want to keep the whitespace. Socowi answers your question. See also [Security implications of forgetting to quote a variable in bash/POSIX shells](https://unix.stackexchange.com/q/171346/4667) – glenn jackman Dec 05 '22 at 16:15
  • See [Bash Pitfalls #14 (echo $foo)](https://mywiki.wooledge.org/BashPitfalls#echo_.24foo). – pjh Dec 05 '22 at 18:01
  • The `echo $(cat example)` (which can be written simpler as `echo $( – user1934428 Dec 06 '22 at 10:55

1 Answers1

4

IFS= read -r line < file is correctly reading unmodified lines with leading and trailing spaces. You can confirm this by printing the variable using declare -p line.

But after you read the lines correctly, you are mangling them during your print commands. Both echo $(cat example) and echo $line have unquoted expansions, which cause the shell to word-split your lines.

Quote them to resolve the problem:

echo "$(cat example)"
echo "$line"

By the way, https://shellcheck.net/ is excellent for spotting and explaining errors like these.

Socowi
  • 25,550
  • 3
  • 32
  • 54