Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

A few years ago I found an interesting code snippet that prints each type of file in its corresponding color according to the colors set up in LS_COLORS. Unfortunately, I can't remember the link anymore.

Here is the snippet test_colors.sh in question

eval $(echo "no:global default;fi:normal file;di:directory;ln:symbolic link;pi:named pipe;so:socket;do:door;bd:block device;cd:character device;or:orphan symlink;mi:missing file;su:set uid;sg:set gid;tw:sticky other writable;ow:other w\
ritable;st:sticky;ex:executable;"|sed -e 's/:/="/g; s/\;/"\n/g')                                                                                                                                                                            
{                                                                                                                                                                                                                                           
  IFS=:                                                                                                                                                                                                                                     
  for i in $LS_COLORS                                                                                                                                                                                                                       
  do                                                                                                                                                                                                                                        
    echo -e "\e[${i#*=}m$( x=${i%=*}; [ "${!x}" ] && echo "${!x}" || echo "$x" )\e[m"                                                                                                                                                       
  done                                                                                                                                                                                                                                      
}   

The snippet works great in bash, but not in zsh, and I can't tell why. When I run it in zsh I get the following error:

> sh .test_colors.sh
.eval_colors:1: * not found
[00:fi=00:di=01;34:ln=01;36: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:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.gz=01;31:*.bz2=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.avi=01;35:*.fli=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.flac=01;35:*.mp3=01;35:*.mpc=01;35:*.ogg=01;35:*.wav=01;35:m

Update (Nov. 1, 2011)

I tested the script by @Stéphane Gimenez below. I noticed that some characters seem to not escape correctly. Any thoughts why?

Answer: See comments on @Stéphane Gimenez's answer.

                                                      enter image description here

share|improve this question
add comment

2 Answers 2

up vote 4 down vote accepted

The same written for zsh in a much cleaner way:

#!/bin/zsh

typeset -A names
names[no]="global default"
names[fi]="normal file"
names[di]="directory"
names[ln]="symbolic link"
names[pi]="named pipe"
names[so]="socket"
names[do]="door"
names[bd]="block device"
names[cd]="character device"
names[or]="orphan symlink"
names[mi]="missing file"
names[su]="set uid"
names[sg]="set gid"
names[tw]="sticky other writable"
names[ow]="other writable"
names[st]="sticky"
names[ex]="executable"

for i in ${(s.:.)LS_COLORS}
do
    key=${i%\=*}
    color=${i#*\=}
    name=${names[(e)$key]-$key}
    printf '\e[%sm%s\e[m\n' $color $name
done
share|improve this answer
    
You might want to replace \n by a space at the end of the printf for compactness maybe. –  Stéphane Gimenez Sep 15 '11 at 0:27
    
Thanks @Stéphane Gimenez. I have updated my OP with a problem I am getting when printing some characters using your script. Not sure if this is strictly related to your script though (it may be my own terminal?) –  user815423426 Nov 1 '11 at 18:09
1  
@intrpc: running zsh as sh your are using some compatibility mode. Either call your script as zsh ./test_color_scheme or add double quotes around $color and $name. –  Stéphane Gimenez Nov 2 '11 at 12:35
    
@Stéphane Gimenez: I was directed here from my related question here: unix.stackexchange.com/questions/52659/… . Your expansion of abbreviations is very helpful. I have three abbreviations, rs, ca and mh that are not included above. Can you please tell me where to find their expansions? Thanks. –  chandra Oct 24 '12 at 5:13
    
Interpreted from dircolors -p rs=reset, ca=capability, mh=multi-hard_link –  weldabar Nov 3 '13 at 20:16
add comment

You need to escape the = in ${i%=*} because otherwise the suffix pattern =* undergoes = expansion, so = is interpreted as a command name. This is the cause of the * not found error.

Zsh doesn't split words on variable substitutions by default, so $LS_COLORS expands to a single word. To have the for loop operate on the colon-separated parts of $LS_COLORS, use for i in $=LS_COLORS. Or more idiomatically in zsh, don't use IFS but instead specify explicitly how to split: for i in ${(s.:.)LS_COLORS}.

The syntax ${!x} to mean “the value of the variable whose name is $x” is specific to bash. Zsh has an equivalent construct, the P parameter expansion flag: ${(P)x}.

share|improve this answer
1  
There are two more reasons for this script is not working in zsh. No automatic word-splitting for LS_COLORS and = needs to be escaped in substitution patterns. –  Stéphane Gimenez Sep 15 '11 at 0:54
    
@StéphaneGimenez You're right, thanks, I only hit on where bash is non-standard but these are two non-standard zsh features that need to be addressed as well. You should expand your answer to have all the explanations, and then I can delete mine. –  Gilles Sep 15 '11 at 7:18
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.