-1

i am trying to find directory or file that ends in any 3 characters with using

ls -l /etc | grep ???$

and this doesnt work,,

what should I type to find any directory of files that ends with 3 or 4 or 5 or 6 or 7 ... characters?

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
jonney Cho
  • 21
  • 1
  • 1

3 Answers3

2
find /etc -maxdepth 1 -regextype egrep  -regex '.*/.{3}$'

This will find file or directory names in /etc/ that are exactly 3 characters long.

find /etc -maxdepth 1 -regextype egrep  -regex '.*/.{3,}$'

And this will find files or directories in /etc/ that are a minimum of 3 characters long.

find /etc -maxdepth 1 -regextype egrep  -regex '.*/.{3,7}$'

And this will find files or directories in /etc that are anywhere from 3 to 7 characters long.

The -maxdepth 1 prevents find from searching sub-directories of /etc.

If you want to restrict the match to directories only, add -type d after the -maxdepth 1. For regular files, use -type f.

If you intend to do anything with the files/dirs found, you can use find's -exec option. e.g.

find /etc -maxdepth 1 -regextype egrep  -regex '.*/.{3,7}$' -exec du -sch {} +

or xargs (but use NUL separators to avoid problems with spaces, newlines, etc in filenames). This allows you to use any tool that can process NUL-separated input in the pipeline before xargs. e.g.:

find /etc -maxdepth 1 -regextype egrep  -regex '.*/.{3,7}$' -print0 | 
  head -z -n 10 |
  xargs -0r ls -ld
cas
  • 78,579
1

To list the names in a single directory (i.e. not recursively) that contain at least three characters, you may use any of the globbing patterns *???, ???* or *???*. Each ? matches a single character, while * matches any number of characters.

To list such names under /etc with ls:

ls -ld /etc/*???

or simply,

printf '%s\n' /etc/*???

If you want to list the names that end in three specific characters (e.g. xyz), then use *xyz as the pattern.

To search for such names recursively, you may (in bash) use shopt -s globstar to enable the ** globbing pattern (matches recursively down into subdirectories) and then...

ls -ld /etc/**/*???

The ** pattern is enabled by default in the zsh shell.

To do something with these names (other than just calling ls), use a loop:

shopt -s globstar
for pathname in /etc/**/*???; do
    # use "$pathname" to do something
done

In the dash shell or plain sh, the equivalent of this loop would be

find /etc -name '*???' -exec sh -c '
    for pathname do
        # use "$pathname" to do something
    done' sh {} +

Related:


Your use of grep shows that you are confusing regular expressions with filename globbing patterns. In a regular expression, a dot (.) matches any one single character, while ? matches just the character ? (at least in basic regular expressions, which is what grep uses by default).

Filename patterns are also always anchored, so there's no need to explicitly anchor the pattern with $ as in a regular expression (the pattern must match the complete filename though, so xyz matches exactly that name while *xyz matches any filename ending in xyz).

Related:

Kusalananda
  • 333,661
0

You can use a find and filter for the result:

find -type f | egrep '3$|4$|5$'
alessiosavi
  • 347
  • 2
  • 9