What is the problem with the output of plink?

18,562

Solution 1

As michas has explained, those are terminal escape sequences. How they are interpreted is up to the terminal. You can do as michas has suggested and call ls like \ls, which will call the ls executable in $PATH, instead of the common shell alias ls --color=auto. To remove that shell alias you could do:

unalias ls

You can also add the option...

ls ${opts} --color=never

...at any time to turn it off. Another way to disable the color sequences for instance is to do:

ls ${opts} | cat

This works, because in the --color=auto mode ls checks its output to determine if it is a tty device and if so, it injects the terminal escapes to colorize its output. When it is not a terminal device - like when it is instead a |pipe file as in the example above - ls prints no escape sequences. This is the standard behavior of most applications that can colorize their output.

More interesting though is the api that most ls implementations provide to control this behavior - which I find interesting and which has prompted me to write this answer.

ls determines which parts of its output to colorize, based on the values in the $LS_COLORS environment variable. The dircolors application is an interface for handling this. For instance, on my machine:

dircolors -p

...
# Below are the color init strings for the basic file types. A color init
# string consists of one or more of the following numeric codes:
# Attribute codes:
# 00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed
# Text color codes:
# 30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white
# Background color codes:
# 40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white
#NORMAL 00 # no color code at all
#FILE 00 # regular file: use no color at all
RESET 0 # reset to "normal" color
DIR 01;34 # directory
LINK 01;36 # symbolic link. (If you set this to 'target' instead of a
 # numerical value, the color is as for the file pointed to.)

... and so on. When compared to...

printf %s "$LS_COLORS"

rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:\
bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:\
ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:...

...we can begin to get an idea of what ls is doing. What is specifically not shown in either of these though, is the compiled in values for...

lc=\e[:rc=m:ec=:

Each of these handles what goes to the left side of a terminal escape code, the right side of a terminal escape code, and the end of a terminal escape sequence. As you can see in the dircolors output, my fi=: is not set as the default - because typically ls does not colorize regular files.

But if we take all of this together and add a little, we can do things like...

mkdir dir ; touch file1 file2
LS_COLORS=\                                    
'lc=\nLEFT_SIDE_ESCAPE_SEQUENCE\n:'\                                                            
'rc=\nRIGHT_SIDE_ESCAPE_SEQUENCE\n:'\
'ec=\nEND_OF_ESCAPE_SEQUENCE:'\
'fi=REGULAR_FILE_ESCAPE_CODE:'\                          
'di=DIRECTORY_ESCAPE_CODE:'\
ls -l --color=always | cat -A
total 0$
drwxr-xr-x 1 mikeserv mikeserv 0 Jul 10 01:05 $
END_OF_ESCAPE_SEQUENCE$
LEFT_SIDE_ESCAPE_SEQUENCE$
DIRECTORY_ESCAPE_CODE$
RIGHT_SIDE_ESCAPE_SEQUENCE$
dir$
END_OF_ESCAPE_SEQUENCE/$
-rw-r--r-- 1 mikeserv mikeserv 0 Jul 10 01:08 $
LEFT_SIDE_ESCAPE_SEQUENCE$
REGULAR_FILE_ESCAPE_CODE$
RIGHT_SIDE_ESCAPE_SEQUENCE$
file1$
END_OF_ESCAPE_SEQUENCE$
-rw-r--r-- 1 mikeserv mikeserv 0 Jul 10 01:08 $
LEFT_SIDE_ESCAPE_SEQUENCE$
REGULAR_FILE_ESCAPE_CODE$
RIGHT_SIDE_ESCAPE_SEQUENCE$
file2$
END_OF_ESCAPE_SEQUENCE$
$
LEFT_SIDE_ESCAPE_SEQUENCE$
$
RIGHT_SIDE_ESCAPE_SEQUENCE$

ls should print the ec escape once at the start of it's output and the lc and rc escapes once at the very end. Every other time they occur is immediately preceding or following a file name. The ec sequence only occurs if it is set - the default behavior is to use the reset or rs sequence, instead in combination with lc and rc. Your output shows a configuration something like:

`lc=\033[:rc=m:rs=0...`

...which is typical, though ec grants you more control. For instance, if you ever wanted a \0null delimited ls, it can be accomplished as simply as:

LS_COLORS='lc=\0:rc=:ec=\0\0\0:fi=:di=:' ls -l --color=always | cat -A                                        
total 0$
drwxr-xr-x 1 mikeserv mikeserv 0 Jul 10 01:05 ^@^@^@^@dir^@^@^@/$
-rw-r--r-- 1 mikeserv mikeserv 0 Jul 10 01:08 ^@file1^@^@^@$
-rw-r--r-- 1 mikeserv mikeserv 0 Jul 10 01:08 ^@file2^@^@^@$
^@%

Again you can see that we get one extra ec just before the first escape sequence is printed and one just at the end. Aside from those two, \0 null bytes only occur immediately preceding or following a filename. You can even see that the extra / slash used to indicate a directory falls outside the nulls enclosing it.

This works fine for file names containing new lines as well:

touch 'new
line
file'
LS_COLORS='lc=\0:rc=:ec=\0\0\0:fi=:di=:' \
ls -l --color=always | cat -A

total 0$
drwxr-xr-x 1 mikeserv mikeserv 0 Jul 10 01:05 ^@^@^@^@dir^@^@^@/$
-rw-r--r-- 1 mikeserv mikeserv 0 Jul 10 01:08 ^@file1^@^@^@$
-rw-r--r-- 1 mikeserv mikeserv 0 Jul 10 01:08 ^@file2^@^@^@$
-rw-r--r-- 1 mikeserv mikeserv 0 Jul 10 01:43 ^@new$
line$
file^@^@^@$
^@%                                       

If we take all of this together we can surmise that, in your case, there are three primary problems, and if either of them is addressed it will likely obviate the others.

  • In the first place, either your terminal device simply does not interpret terminal color escapes correctly or plink is in some way rendering them unreadable for your terminal. I'm not sure which is true, but the plink docs have this to say about it:

The output sent by the server will be written straight to your command prompt window, which will most likely not interpret terminal control codes in the way the server expects it to. So if you run any full-screen applications, for example, you can expect to see strange characters appearing in your window. Interactive connections like this are not the main point of Plink.

In order to connect with a different protocol, you can give the command line options -ssh, -telnet, -rlogin or -raw. To make an SSH connection, for example:

Z:\sysosd>plink -ssh login.example.com
login as:

If you have already set up a PuTTY saved session, then instead of supplying a host name, you can give the saved session name. This allows you to use public-key authentication, specify a user name, and use most of the other features of PuTTY:

Z:\sysosd>plink my-ssh-session
Sent username "fred"
Authenticating with public key "fred@winbox"
Last login: Thu Dec  6 19:25:33 2001 from :0.0
fred@flunky:~$
  • If either of those options either does not work for you or is otherwise not feasible, then you can address this by maybe running a check against plink in your .${shell}rc file that is sourced at login. You might thereby enable the ls alias, only if your login device is not a plink connection. Alternatively, you could remove it altogether, I suppose, but doing so will render ls colorless for any login session. You might also add an unalias ls or even alias ls='ls --color=never command to plink's login command and thereby only remove the alias, when logged in with plink.

  • The last problem is that ls - regardless of it's aliased command line options - is provided an environment specifying terminal escapes in $LS_COLORS. Similar to the latter case of problem 2, you could simply set $LS_COLORS to a null value when logging in with plink. In that way, there will be no color codes to render and ls --color=auto will make no difference at all.

Solution 2

Those are escape sequences to set colors:

  • ←[00;34 tries to turn on blue color
  • ←[00m tries to reset the color

It is up to your terminal to interpret those sequences and do the coloring.

The real putty brings it's own terminal, which is able to interpret these.

If you use plink, you are using your windows terminal, which is not able to do so and simply prints them out.

On the remote host type type ls, which should print something like:

ls is aliased to `ls --color=auto'

This --color=auto is generating those color sequences. If you disable the alias by typing \ls, the coloring sequences are gone.

Solution 3

You may find this helpful:

http://adoxa.altervista.org/ansicon/

If you call plink as an argument of ansicon.exe, this translates the escape sequences automatically. When I connect to my linux box, the output of ls is coloured automatically.

Solution 4

You may want to run plink in the PowerShell command window, which can show ANSI chars properly, or in the cmd.exe window, run this:

C:\Users\decui>powershell plink.exe [email protected]

(I tested this in Win10)

Share:
18,562

Related videos on Youtube

Keyshov Borate
Author by

Keyshov Borate

In God we Trust, all others bring data - W. Edwards Deming If you want to travel around the world and be invited to speak at a lot of different places, just write a Unix operating system. - Linus Torvalds The universe is not required to be in perfect harmony with human ambition. - Carl Sagan

Updated on September 18, 2022

Comments

  • Keyshov Borate
    Keyshov Borate over 1 year

    On my Windows7 machine, I'm traversing to the installed path of PuTTy Application and running:

    plink <hostname>
    

    to connect to my remote Linux host.

    I see some unrecognized characters in the output as:

    -bash-3.2$ ls -lrt
    ←[00mtotal 96
    drwx------ 5 lg262728 lg262728  4096 Jun 10 15:32 ←[00;34mmyScripts←[00m
    drwx------ 2 lg262728 lg262728  4096 Jun 12 13:19 ←[00;34mmyLangs←[00m
    drwxr-xr-x 4 lg262728 lg262728  4096 Jul  1 07:43 ←[00;34mmyWorkSpace←[00m
    ←[m-bash-3.2$
    

    What is wrong here? Is it something about encoding?

  • Keyshov Borate
    Keyshov Borate almost 10 years
    cool! Anyway to permanently disable the color, or to literate the windows command prompt to get to know what this "←[00;34" & "←[00m" is.
  • Keyshov Borate
    Keyshov Borate almost 10 years
    very good explanation, specially of colour codes, but ls | cat wont give me ls -l type output, thanks though!
  • mikeserv
    mikeserv almost 10 years
    @Keys - no you'd have to do ls -l | cat
  • michas
    michas almost 10 years
    To permanently disable this, find the place where the alias is set. This is probably some init file like ~/.bashrc or ~/.profile. Just remove/uncomment the alias there.
  • Keyshov Borate
    Keyshov Borate almost 10 years
    just did, but hows the whole thing working, as far as I was knowing cat needs a file name as a parameter, here we're just passing that output to cat!
  • mikeserv
    mikeserv almost 10 years
    @Keys - well, cat's primary purpose is to concatenate its stdin with its stdout. Well... ok, so it can also add existing files specified on the command line to its stdin but it's still just concatenating two streams - <in to >out. I use it above in some of the examples because the GNU version can also interpret and display control characters - the ^@ represent NUL bytes. In any case the |pipe file is its stdin - which is also ls's stdout - and your terminal is cat's stdout so it does < ls in > $TTY out.
  • Ekaterina Klishina
    Ekaterina Klishina almost 7 years
    Does not work under Win7. Or did you mean ISE? That might have worked but simply hangs for me.
  • stiv
    stiv about 4 years
    for me it doesn't work on W10, it can't show characters