38

I have to write a script that finds all executable files in a directory. So I tried several ways to implement it and they actually work. But I wonder if there is a nicer way to do so.

So this was my first approach:

ls -Fla | grep \*$

This works fine, because the -F flag does the work for me and adds to each executable file an asterisk, but let's say I don't like the asterisk sign.

So this was the second approach:

ls -la | grep -E ^-.{2}x 

This too works fine, I want a dash as first character, then I'm not interested in the next two characters and the fourth character must be a x.

But there's a bit of ambiguity in the requirements, because I don't know whether I have to check for user, group or other executable permission. So this would work:

ls -la | grep -E ^-.{2}x\|^-.{5}x\|^-.{8}x

So I'm testing the fourth, seventh and tenth character to be a x.

Now my real question, is there a better solution using ls and grep with regex to say:

I want to grep only those files, having at least one x in the ten first characters of a line produced by ls -la

codeforester
  • 39,467
  • 16
  • 112
  • 140
k13n
  • 787
  • 1
  • 8
  • 8
  • 4
    Thank you for actually finding some kind of solution before asking for help. Since you had the requirement of using ls and grep, it seems like a homework question and I see people asking for answers to homework with no attempt (or at least no description of their attempts). I know it is almost 4 years later, but even so, good job. – Ross Bradbury Jun 15 '15 at 15:31

6 Answers6

62

Do you need to use ls? You can use find to do the same:

find . -maxdepth 1 -perm -111 -type f

will return all executable files in the current directory. Remove the -maxdepth flag to traverse all child directories.

You could try this terribleness but it might match files that contain strings that look like permissions.

ls -lsa | grep -E "[d\-](([rw\-]{2})x){1,3}"
jozxyqk
  • 16,424
  • 12
  • 91
  • 180
Dan
  • 995
  • 6
  • 6
55

If you absolutely must use ls and grep, this works:

ls -Fla | grep '^\S*x\S*'

It matches lines where the first word (non-whitespace) contains at least one 'x'.

Find is the perfect tool for this. This finds all files (-type f) that are executable:

find . -type f -executable

If you don't want it to recursively list all executables, use maxdepth:

find . -maxdepth 1 -type f -executable
Alexander Pozdneev
  • 1,289
  • 1
  • 13
  • 31
rmmh
  • 6,997
  • 26
  • 37
  • Than you for your answer and `find . -type f -executable` works perfectly. But as I said before I have to use ls and grep. I'm just wondering if there is a solution for a smarter regex – k13n Oct 18 '11 at 19:11
  • 1
    Any particular reason? looping through ls output is a bad idea. – Spencer Rathbun Oct 18 '11 at 19:13
  • Okay, I added a regex that will do what you want. – rmmh Oct 18 '11 at 19:30
  • To cut the starting "./" use `find . -maxdepth 1 -type f -executable | cut -c 3-` – Alexander Pozdneev Oct 22 '15 at 12:37
  • 4
    ***NOTE***: `-executable` flag is not available under macOS. See [here](https://apple.stackexchange.com/a/116371) for alternatives. (for those who came here through some search engine!) – Yan Foto Nov 21 '17 at 12:19
9

Perhaps with test -x?

for f in $(\ls) ; do test -x $f && echo $f ; done

The \ on ls will bypass shell aliases.

David Poole
  • 3,432
  • 5
  • 34
  • 34
  • 3
    AFAICS that also lists directories. The OP might be better with... `for f in $(\ls) ; do /usr/bin/test -x $f -a ! -d $f && echo $f ; done` – Simon F Apr 22 '16 at 10:42
5
for i in `ls -l | awk '{ if ( $1 ~ /x/ ) {print $NF}}'`; do echo `pwd`/$i; done

This gives absolute paths to the executables.

user842679
  • 51
  • 1
  • 3
2

While the question is very old and has been answered a long time ago, I want to add the version for anyone who is using the fd utility (which I personally highly recommend, see https://github.com/sharkdp/fd if you want to try), you get the same result as find . -type f -executable by running:

fd -tx

or

fd --type executable

One can also add -d or --max-depth argument, same as for the original find.

Maybe someone will find this useful.

nomæd
  • 421
  • 5
  • 13
-3
file * |grep "ELF 32-bit LSB executable"|awk '{print $1}'
Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
  • 1
    This answer turned up in the low quality review queue, presumably because you don't provide any explanation of the code. If this code answers the question, consider adding adding some text explaining the code in your answer. This way, you are far more likely to get more upvotes — and help the questioner learn something new. – lmo Aug 30 '16 at 22:56