-3

I am writing a bash script that needs to takes in command line arguments, and list the number of executable files in the current directory.

So for: $ ./script *.html *.txt

It should display the count of all executable files that match those command line arguments, or the lack of.

Right now I have:

echo -n "All executable files : " ls -l $* | find . -type f -executable | wc -l

But I get ls: write error: Broken pipe.

How would I accomplish this?

Alex
  • 27
  • 1
  • 5
  • 5
    First of all, [don't parse the output of `ls`](http://mywiki.wooledge.org/ParsingLs). It's always the wrong thing to do. Second, this is plainly an [XY Problem](http://xyproblem.info/), as you're asking for help in implementing your (broken) solution, rather than solving the core problem. While it's commendable that you've included your attempt to write something inyour question, please also include an example of the output you expect to see. – ghoti Feb 22 '16 at 17:15
  • Okay, well I am new to this, so if there is a better solution, I would obviously want to hear it. I am looking to get a count of executable only files, in a directory, based on any number of command line arguments. So if there are ten files in a directory. Half of them read only, and half of them executable. And if I run a script `./script file* *.txt`, it would show me the count of all the files that start with file, end with .txt, and are executables. – Alex Feb 22 '16 at 17:47
  • Welcome to StackOverflow, then! We're a (mostly) friendly bunch. When adding details that will help us understand your question, [***edit your question***](http://stackoverflow.com/posts/35559358/edit) with the "edit" link under your question, don't just add comment. – ghoti Feb 22 '16 at 19:53
  • Possible duplicate of [Recursively count specific files BASH](http://stackoverflow.com/questions/6268863/recursively-count-specific-files-bash) – miken32 Feb 22 '16 at 20:53

4 Answers4

2

To start, you need to quote the arguments to your script, so that the patterns are not expanded to any matching files in the current directory before your script is even called.

$ ./script "*.html" "*.txt"

Inside your script, you'll build up an appropriate set of arguments for find using the script arguments. Even assuming parsing the output of ls was a good idea (it's not), find doesn't read from its standard input.

to_match=()
for pattern in "$@"; do
    to_match+=(-name "$pattern" -o)
done
unset to_match[${#to_match[@]}]  # newer versions of bash can use -1 as the index

find . -type f -executable \( "${to_match[@]}" \)
chepner
  • 497,756
  • 71
  • 530
  • 681
1

a bash script that needs to takes in command line arguments, and list the number of executable files in the current directory.

This bash function should work with stat command:

lsexecs() {
    local c=0

    # loop through file globs supplied on command line
    for i in $@; do
       # read octal permissions for this file
       perm=$(stat -c '%a' "0$i")

       # perform bitwise AND with 0111 to find executables and count them
       ((perm & 0111)) && echo "$i" && ((c++))

       echo "count: $c"
    done
}

Now call this function as:

lsexecs '*.sh *.py *.pl'

Or else:

lsexecs '*.sh' '*.py' '*.pl'
anubhava
  • 761,203
  • 64
  • 569
  • 643
1

In your script, you can do the following:

#!/bin/bash

count=0          
num_args="$#"     

for (( i = 0; i < "$num_args"; i++ )); do
    num=`find . -type f  -perm /u=x,g=x,o=x -name "$1" | wc -l`
    count=$(( count + num ))
    shift
done

echo "$count"

Usage:

$ ./script "*.html" "*.txt"       # can add any number of arguments here
assefamaru
  • 2,751
  • 2
  • 10
  • 14
0

try this

find . -type f  -executable -name "*.html" -o -name "*.txt" | wc -l

alternative use:

find . -type f  -perm 777 -name "*.html" -o -name "*.txt" | wc -l

find . -type f  -perm /u=x,g=x,o=x -name "*.html" -o -name "*.txt" | wc -l

Regards

Claudio

ClaudioM
  • 1,418
  • 2
  • 16
  • 42
  • Okay, that makes sense. But what if I want to do it for any number of command line arguments? – Alex Feb 22 '16 at 17:08
  • Note that the `-executable` option is not portable -- it appears to be included in GNU find (in coreutils), but is not in FreeBSD, OSX, etc. While I grant you the question is tagged "linux", there is a non-Linux audience here too, and portable answers are always preferable. Also, different implementations of `find` will output newlines in filenames differently, so your wordcount may be only approximate. – ghoti Feb 22 '16 at 17:16
  • @Alex what do you mean? – ClaudioM Feb 22 '16 at 17:24
  • @ghoti, yes you're right maybe it's better to use -perm – ClaudioM Feb 22 '16 at 17:25
  • I guess OP is looking for a solution where `*.html` or `*.txt` are not "hard coded" but configurable through "command line arguments". – mauro Feb 22 '16 at 17:27
  • Did you test it? I think you have to "group" the two -name switches: `find ... -type f \( -name \*.html -o -name \*.txt \) ...` – mauro Feb 22 '16 at 17:35
  • Yes, that is exactly what I am looking for. What if the user supplies his own arguments... and any number of them? like `./script *.html *.txt *.hey something* something2*` etc etc – Alex Feb 22 '16 at 17:36
  • @ghoti What you are saying is true, just a hint, (GNU) `find` is part of `findutils`, not `coreutils`. – hek2mgl Feb 22 '16 at 17:45
  • @hek2mgl - ah, thanks. :) With FreeBSD as my primary focus, I do sometimes miss details like that. – ghoti Feb 22 '16 at 19:51