Search code examples
bashmsys2

back ticks messing with output of command


For example:

ipconfig > temp
cat temp

Yields the correct results (all the output from ipconfig).

However:

ipconfig > temp
echo `cat temp`

Yields very wrong results:

Connection-specific DNS Suffix . :: Media disconnected2A612}:%62

That's it, nothing more is being printed, which is clearly wrong becuase if I open up temp in an editor I can clearly see the correct output.


Solution

  • To make it work, change echo `cat temp` to echo "`cat temp`".

    There are several reasons why you are experiencing this issue:

    Unquoted command substitution

    echo `cat temp` is a form of unquoted command substitution, which will result in word splitting (and also globbing).

    Whitespace, which includes the newline character \n, is considered a delimiter by bash, so it will treat any bit of text separated by whitespace as an element in an array, and then pass each element as its own argument to whatever command uses the substitution. echo will output each argument it receives separated by spaces:

    $ echo `echo Line 1; echo Line 2; echo Line 3`
    Line 1 Line 2 Line 3
    

    However, when you quote the substitution, word splitting is not applied, so \n is treated as a string literal:

    $ echo "`echo Line 1; echo Line 2; echo Line 3`"
    Line 1
    Line 2
    Line 3
    

    Windows line endings

    Windows, unlike *nix OS's, doesn't use the newline character \n as a line break. Instead, it uses a combination of the carriage return character \r and the newline character \n, or in other words, \r\n.

    In a POSIX environment, \r in the terminal, much like on a typewriter, returns the current position to the beginning of the line.

    Therefore, usually you won't see much of an issue reading a Windows-formatted file on Linux, because while it has the extra \r characters, it still includes an \n. The two being used in tandem has the same effect: return to the front of the line and then move to the next line. Redundant, but still gets you to the same place.

    So why is this happening, then?

    Keep in mind I said it usually doesn't cause an issue to have \r characters when reading a file (or stream, or something else) in *nix. But here you have an example of a situation where this isn't the case.

    Here's a step-by-step of what's happening when you run ipconfig > temp; echo `cat temp`:

    1. ipconfig.exe runs and its output is redirected to the file temp.
    2. cat temp runs and its output is parsed by bash.
    3. The command substitution is unquoted, so bash splits the results by whitepsace.
    4. The split result is passed to echo.
    5. echo prints the arguments separated by spaces.
    6. Eventually, echo prints the last piece of text on the first line that was outputted by ipconfig.exe. However, the line contains an \r at the end, as ipconfig.exe is a Windows command and uses Windows line endings, so after that bit of text is printed, the position in the terminal returns to the beginning of the line.
    7. echo continues to print arguments, but each time it prints an \r, subsequent output overwrites text already printed from the beginning of the line.

    And this is exactly why you get the output you do. As you stated, you got

    Connection-specific DNS Suffix . : Media disconnected2A612}:%62
    

    Therefore, I'm guessing the last line ipconfig.exe outputted was

    Connection-specific DNS Suffix . : Media disconnected
    

    and that the longest line of text it printed ended in 612}:%62 (probably the IPv6 address), and the second longest ended in 2A.