5

I'd like to find all files in a certain folder which have a filename of at least n characters (extension included). Is there any way to achieve this with find?

5

You could use the find command with a -regex test

$ find /path/to/folder -regextype posix-basic -regex '.*/.\{5,\}'

or

$ find /path/to/folder -regextype posix-extended -regex '.*/.{5,}'

Note that -regex is a path match rather than a file match - hence you need to match the leading .*/ as well, before the 5+ character filename


Alternatively, for a pure bash solution, you could enable extended shell globbing and then use the pattern !(@(?|??|???|????)) meaning 'anything that does not match one or two or three or four characters'

$ shopt -s extglob
$ ls -d /path/to/folder/!(@(?|??|???|????))

If you want to include subdirectories, you can enable the globstar option as well and add a ** wildcard i.e.

$ shopt -s extglob globstar
$ ls -d /path/to/folder/**/!(@(?|??|???|????))

for example

$ ls -d **/!(@(?|??|???|????))
abcde  abcdef  abcdefg  subdir  subdir/abcde  subdir/abcdef  subdir/abcdefg

while the non inverted matches (files shorter than 5 characters) are

$ ls -d **/@(?|??|???|????)
a  ab  abc  abcd  subdir/a  subdir/ab  subdir/abc  subdir/abcd

To unset the options afterwards, use

$ shopt -u extglob globstar
  • +1 Nice solutions, although they don't work for n as a minimum in general. – user54813 Oct 19 '13 at 18:56
  • Thank you @htor - on reflection, there doesn't seem to be any reason to prefer !(@(?|??|???|????)) over @Radu Rădeanu's much simpler ?????* - perhaps I should delete the suggestion? – steeldriver Oct 19 '13 at 19:08
  • When I first saw your answer, I just skipped because it seemed too complex. Then when no other answer was working, I came back to your answer and found that I actually did not need to read Alternatively, for a pure bash onwards. I think if you just omit rest of the answer, you will get better response. It is just my suggestion, may be wrong. – blueray Nov 28 '19 at 5:49
8

I think the simplest way is to use:

find . -name "??????????*"

where the number of ? characters is equal with n. Is simple because is hard to forget it.

But the nicest way is to use the -regex option to find file names with n or more characters:

find . -regextype posix-egrep -regex ".*[^/]{n}"

where n should be a natural number (the minimum filename length).

See man find fore more about.

  • When I give find . -regextype posix-egrep -regex ".*[^/]{n}" it says, find: ‘./lost+found’: Permission denied. If I invoke the command with sudo, it yields no results. – blueray Nov 28 '19 at 5:44
1

Python approach:

#!/usr/bin/env python
from __future__ import print_function
import os,sys


def main():
    treeroot = sys.argv[1]
    base_len = int(sys.argv[2])
    for dir,subdirs,files in os.walk(treeroot):
         for f in files: 
             if len(f) >= base_len:
                 fullpath = os.path.abspath(os.path.join(dir,f))
                 print(fullpath)

if __name__ == '__main__' : main()

Usage is simple:

./find_files_len.py /path/to/top_directory/  minimal_length

For example:

./find_files_len.py /etc  5 

That'll give us all files with basename of at least 5 characters , found recursively through /etc/ and all its subdirectories. Note that full path of the file will be printed to the command-line

0

You could loop over the list of files returned by find and test the length of each file's basename:

min_fname() {
    for path in $(find "$1" -type f); do 
        bn="${path##*/}"
        if (( "${#bn}" >= $2 )); then 
            echo "$path" 
        fi 
    done
}

# usage: min_fname dir value

$ min_fname /tmp 5
$ min_fname /home/user 10

This function uses only find and Bash builtin mechanisms, and no regex matching. Put this function definition in the ~/.bashrc file to make the min_fname command persistent between logins.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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