Find all files in the current directory and its subdirectories with the extension .png

31,839

Solution 1

The correct use is

 ls -R | grep '\.png$'

This command only works with normal file names with no space, new line or special characters. Use find as suggested by danzel or globstar as suggested by DoVo.

Solution 2

TL;DR

To find files matching a regular expression, use find with the -regex option:

find [startingPath] -type [fileType] -regex "[regularExpression]"

In your case, if you want to search for files (file type f) ending in .png, starting from the current directory:

find . -type f -regex ".*\.pdf"

If you want to have an ls-like output, use the -ls action:

find . -type f -regex ".*\.pdf" -ls

(the output has the same format as ls -dils).

If you want to execute a command for each file, use the -exec action, e.g.:

find . -type f -regex ".*\.pdf" -exec file {} \;

... will print file type information for each matching file.

There are a lot more things you can do with find, just read the manual.


As @steeldriver said in the comment, there is no regular expression in your command. *.png is a shell glob and is expanded before ls is run. Imagine there are two files in the current directory:

picture1.png
picture2.png

...then ls -R *.png will be expanded to:

ls -R picture1.png picture2.png

In this case, the -R option is not particularly useful because there are no directories specified that ls could recurse into.

If the shell doesn't find any matching name, it passes the argument literally (depends on the shell, but bash does):

ls -R *.png

... and ls complains because there is no file called *.png.

Solution 3

Another option instead of find would be the use of globstar:

shopt -s globstar
ls **/*.png

Optionally unset globstar afterwards:

shopt -u globstar

From bash manpage:

globstar
    If set, the pattern ** used in a pathname expansion context will
    match all files and zero or more directories and subdirectories.
    If the pattern is followed by a /, only directories and
    subdirectories match.
Share:
31,839
Mr Brown
Author by

Mr Brown

Updated on September 18, 2022

Comments

  • Mr Brown
    Mr Brown almost 2 years

    In a directory and its subfolders I need to see all the files with the png extension.

    For this, I used the command ls -R *.png

    I get an error saying that the directory *.png doesn't exist. I am surprised that my regular expression is not recognized.

    ls: Cannot read '*.png': the file or the directory doesn't exist
    
    • steeldriver
      steeldriver over 5 years
      ... to find all the files with extension .png in the current directory and all its subdirectories, use find . -name '*.png' rather than trying to filter the output of ls -R
    • Mr Brown
      Mr Brown over 5 years
      @steeldriver Tranks you, this command run well.
  • steeldriver
    steeldriver over 5 years
    grep .png$ may appear to work, but will match any character before png (not just dot)
  • PerlDuck
    PerlDuck over 5 years
    +1 as @steeldriver said. But please note that * and . have different meaning in -regex ".*\.pdf" and -name "*.png".
  • pLumo
    pLumo over 5 years
  • danzel
    danzel over 5 years
    @PerlDuck good point. -name takes a shell pattern (which is matched using the fnmatch function). Since the OP explicitly asked about regular expressions, I concentrated on that.