1

I'm trying to do something like this (logic wise) but it's not working:

if (ls | wc -l ) >100; echo "too many files!"

else ls;

the point is adding this to my bashrc.

Any ideas?

Just an edit because I think I was slightly misunderstood. What I want is that when I type ls (or an alias that runs a modified ls) anywhere the files are only listed when there aren't a lot of them (I want something to add to my .bashrc). Being a bit of a moron, I sometimes type ls in directories where I have thousands of files so I'd like a way to circumvent that.

6 Answers 6

3

Rather than parsing ls, which is not best practice, you can do this with a bash array:

files=(*)
if ((${#files[@]} > 100)); then echo 'Too many files!'; else ls; fi

Probably in the actual problem you want a specific directory, and not the CWD; in that case, you might want something like this:

files=(/path/to/directory/*)
if ((${#files[@]} > 100)); then
  echo 'Too many files!'
else (
       cd /path/to/directory
       ls
     )
fi

Note that I've wrapped the cd into a parenthesized compound command, which means that the cd will be local. That assumes that you don't actually want the full path to appear in the output of ls.

2

You can do using find:

numFiles=$(find . -maxdepth 1 ! -name . -print0 | xargs -0 -I % echo . | wc -l)
(( numFiles > 100 )) && echo "too many files!" || ls

You can make this as function and put it in .bashrc

1

As others have pointed out, this is not an accurate way to count the number of files you have. It will miscount files that contain newlines for example and can have other issues. It is, however, a perfectly good way to count the number of lines that ls will print and not show them if they're too many which is what you're presumably trying to do.

So, to answer your general question, to make one command depend on the result of another, you can use one of

command1 && command2

That will run command2 only if command1 was successful. If you want the second to be executed only if the first's results pass some test you can use:

[ command1 ] && command2

For your example, that would be:

[ $(ls | wc -l) -gt 100 ] && echo too many

To also execute ls again if the test is passed, use either

[ $(ls | wc -l) -gt 100 ] && echo too || ls

or

if [ $(ls | wc -l) -gt 200 ]; then echo 'too many files!'; else ls; fi

However, all of these are inelegant since they need to run the command twice. A better way might be to run the command once, save its output to a variable and then test the variable:

x=$(ls); [ $(wc -l <<<"$x") -gt 100 ] && echo 'too many!' || printf "%s\n" "$x"

Here, the output of ls is saved in the variable $x, then that variable is given as input to wc and if it has more than 100 lines, a message is printed. Else, the variable is.


For the sake of completeness, here's another safe approach that will count files correctly:

[ $(find -maxdepth 1 | grep -cF './') -gt 100 ] && echo 'too many!' || ls
0

A quick one liner:

test `find . -maxdepth 1 -type f|wc -l` -gt 100 && echo "Too Many Files"
0

A short one

[ $(ls | wc -l ) -gt 100 ] && echo too many
0

Combining some of the responses above - a simple Alias:

alias chkls='MAX=100 ; F=(*) ; if [[ ${#F[*]} -gt ${MAX} ]] ; then echo "## Folder: $(pwd) ## Too many files:  ${#F[*]} ##" ; else ls ; fi '

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