Is it possible to make ls distinguish executable scripts from actual compiled binaries?

The permissions are most often the same (+x), and with ls -F you get an asterisk suffix (*) for both, so it's hard to tell them apart. I have a script to setup the colors of ls, but it relies on the file being executable or not, so they show up the same:

BG='01;32'  # green
EX="ex=$BG" # file with execute permission

I don't want to depend on the extension as so many of these files don't have it.

I want this so when I see some bizarre error message and think, "What code caused that?", I know whether or not it's safe to cat the file.

If there is no standard solution, what about parsing the output of file, in one common function, and inserting some distinctive mark? Or would that be much too slow for ls?

  • 4
    At the bare minimum you'll probably have to check (as in read) the first 2 bytes of every executable file you ls (#! probably means script, ^?E probably means the start of a binary). How much of an effect this has probably depends on things like your file system and directory layout and whether you are using spinning disks or solid state, etc. If you do that you probably want noatime or relatime. I think it would be much easier to just run file manually on the few files you want to inspect, unless you truly want to do this for every ls.
    – jw013
    Nov 6, 2012 at 19:36
  • @jw013: Hm, maybe it is smarter to base that check on cat, and not ls? I could call it ct or something similar so it won't interfere with other use of cat. Nov 6, 2012 at 19:55
  • 1
    That's probably a better way to go - replace cat with a shell function that checks if it's a binary file first and warns before outputting to a terminal. I think less already does this check.
    – jw013
    Nov 6, 2012 at 20:04
  • Why do you need this for every file? Just check file before catting something
    Jul 8, 2014 at 17:14

2 Answers 2


You need to look at the contents of a file to distinguish between binaries and scripts. ls won't do this, it only looks at file names and metadata (type, permission, etc.).

Here's a crude parser for file that colors scripts and binaries differently. It acts like ls -d; adding metadata would require a patch-up job that calls for a more direct approach (e.g. in Perl or Python); use lsx somedir/* to list the contents of a directory. File names are assumed not to contain newlines nor colons (you can change the : separator for some other string with the -F option to file).

lsx () {
  file -iN -- "$@" |
  while IFS= read -r line; do
    name=${line%%: *}; type=${line#*: }
    case $type in
      application/x-executable*) color='32';;
      text/x-shellscript*) color='01;32';;
      application/*zip*) color='31';;
    printf '\033[%sm%s\033[0m\n' "$color" "$name"

You could play around with dircolors. Have a look at the output of dircolors -p. On my systems I find the following relevant definitions:

# This is for files with execute permission:
EXEC 01;32
# Or if you want to colorize scripts even if they do not have the
# executable bit actually set.
#.sh 01;32

If you remove the # at the last line and write .sh 07;31 your shell scripts (all files with extension .sh) will blink in red color.

Save your settings in ~/.dircolors and add to your .bashrc the line:

eval "$(dircolor $HOME/.dircolors)"
  • Yes, I'm aware of this. It's very far from a silver bullet solution (as I said, a lot of scripts don't have extensions), and those who do... well, you already know they are scripts (unless you go crazy naming binaries)! Right now, I can't see how this would help me but ... what the heck, I've been wrong before. +1 Nov 6, 2012 at 20:41
  • Sorry, I didn't read about your naming schemes. However in that case you have to check the output of file. I would assume that zsh has a solution for your case, but I'm not sure about this.
    – qbi
    Nov 6, 2012 at 20:46

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .