O motivo é que ls sempre coloriza sua saída mesmo se estiver conectado a um terminal. De man ls :
--color[=WHEN]
colorize the output. WHEN defaults to 'always' or can be
'never' or 'auto'. More info below
Muitas outras ferramentas, como grep , não retêm cores quando a saída padrão é terminal, mas por alguns motivos ls foi projetado para agir de maneira diferente. A saída de colorização é obtida usando códigos de escape ANSI que são interpretados pelo seu terminal. Redirecione ls output para um arquivo e abra-o no editor:
$ ls --color -lhaF1 > /tmp/RESULT
$ less /tmp/RESULT
total 12K
drwxr-xr-x 3 ja users 4.0K Feb 2 09:47 ESC[0mESC[01;34m.ESC[0m/
drwxrwxrwt 12 root root 4.0K Feb 2 09:51 ESC[30;42m..ESC[0m/
drwxr-xr-x 2 ja users 4.0K Feb 2 09:47 ESC[01;34m.invisibleESC[0m/
-rw-r--r-- 1 ja users 0 Feb 2 08:35 a|a
Se você tiver o valor da variável $LESS , provavelmente precisará desativá-lo antes de executar less para ver os códigos de escape brutos em vez da cor. Então, para resumir, quando usar --color o que grep obtém não é o que você vê, mas um monte de códigos de escape junto com ele. Para corrigir isso, não use --colors ou configure-o como --auto :
$ ls --color=auto -lhaF1 | grep -E '^d.*[0-9]{2}:[0-9]{2} \.'