203

I am trying to look for all XML files in a particular directory and all sub-directories (recursively) inside it.

ls -R *.xml is only listing files in the current directory. I am quite sure, the sub-folders themselves have several .xml files, but none are showing up.

Is this a configuration issue?

1
  • 5
    You can do ls -R | grep .xml
    – KeyC0de
    Apr 16, 2017 at 18:03

5 Answers 5

242

You can do it with find only:

find . -name '*.xml'

. is the current directory. If you need to search in another directory, replace . with the directory path.

8
  • 4
    Does it search for the required file recursively in the directory rooted at current directory. In my case it just checked in the current directory only, didn't check the subdirectory. Sep 30, 2014 at 20:24
  • 1
    @mostafiz, you need to quote the '*.xml' part. I'll edit my answer.
    – KaeruCT
    Oct 1, 2014 at 14:39
  • 1
    Actually I searched for .php files in current directory. But it returned only .php files in current directory, didn't searched recursively in sub-directories. That's why I'm asking whether find command searches recursively or not. Oct 1, 2014 at 16:52
  • 4
    @mostafiz, the find command searches recursively. If you don't quote the parameter, I think your shell might do an expansion on the *, so it will match the files in the current directory.
    – KaeruCT
    Oct 1, 2014 at 19:38
  • 1
    you can use -regex or -iregex instead of -name if you want to use a regex.
    – Kip
    Jan 3, 2017 at 21:24
134

Try using Find

sudo find . -print | grep -i '.*[.]xml'
9
  • 4
    is the sudo must, or it's there to ensure super user privileges? Jun 13, 2013 at 20:36
  • 4
    I let you decide. Sudo, No Sudo.
    – Mitch
    Jun 13, 2013 at 20:44
  • 6
    Just out of interest. What is the advantage of find over ls -R?
    – don.joey
    May 22, 2014 at 9:21
  • 1
    @don.joey This might help stackoverflow.com/questions/13830036/…
    – Mitch
    May 22, 2014 at 10:08
  • 16
    -1 for mixing find and grep, when find can do filtering using both regexes and globs, and not using find's -print0 and grep's -z when you do need to mix.
    – muru
    Apr 3, 2015 at 6:54
24

Try this command:

ls -R | grep '.*[.]xml'

ls doesn't have options to filter the output. For that you would need to use pipe. This passes the output from ls to grep, which then filters them to show just the .xml files.

2
  • 10
    Anyway to get this to show the directory it came from?
    – AdamO
    Jul 28, 2015 at 20:55
  • 3
    Mandatory link: Why not parse ls?
    – Ruslan
    Apr 24, 2017 at 11:02
6

bash

Using globstar shell option, we can make use of recursive globbing ./**/*

bash-4.3$ shopt -s globstar
bash-4.3$ for i in  ./**/*.xml; do printf "%s\n" "$i" ; done
./adwaita-timed.xml
./bin/hw5/stuff/book/chapter42servletexample/build/web/META-INF/context.xml
./bin/hw5/stuff/book/chapter42servletexample/build/web/WEB-INF/beans.xml
./bin/hw5/stuff/book/chapter42servletexample/build/web/WEB-INF/web.xml

Perl

Perl has a module Find, which allows for recursive directory tree traversal. Within the special find() function, we can define a wanted subroutine and the directory that we want to traverse, in this example that's .. The one-liner in such case would be:

bash-4.3$ perl -le 'use File::Find; find(sub{-f && $_ =~ /.xml$/ && print $File::Find::name},".")' 
./adwaita-timed.xml
./CLEAR_DESKTOP/blahblah/hw5/stuff/book/jsf2demo/build/web/WEB-INF/beans.xml
./CLEAR_DESKTOP/blahblah/hw5/stuff/book/jsf2demo/build/web/WEB-INF/web.xml
./CLEAR_DESKTOP/blahblah/hw5/stuff/book/liangweb/build.xml

Python

While Perl has a whole module dedicated to recursive tree traversal, Python has a neat function walk() that is part of os module, and repeatedly returns tuple of topmost path, list of all subdirectories, and list of filenames. We can do the following:

bash-4.3$ python -c 'import os,sys; [ sys.stdout.write(os.path.join(r,i)+"\n") for r,s,f in os.walk(".") for i in f if i.endswith(".xml") ]' 
./adwaita-timed.xml
./CLEAR_DESKTOP/blahblah/hw5/stuff/book/jsf2demo/build/web/WEB-INF/beans.xml
./CLEAR_DESKTOP/blahblah/hw5/stuff/book/jsf2demo/build/web/WEB-INF/web.xml
./CLEAR_DESKTOP/blahblah/hw5/stuff/book/liangweb/build.xml

This might be far neater as a script:

#!/usr/bin/env python
import os,sys 
for r,s,f in os.walk("."): 
    for i in f: 
        if i.endswith(".xml") 
             print(os.path.join(r,i))

find

Other answers have mentioned find for recursive traversal, and that's the go-to tool for the job. What does need mention is the fact that find has multiple command line switches, such as -printf to print output in desired format, -type f to find only regular files, -inum to search by inode number, -mtime to search by modification date, -exec <command> {} \; to execute a particular command to process the file with passing file as argument ( where {} is standard find placeholder for current file) , and many others so please read the manpage for find.

0

Inside the Gnome Filemanager you can click on the magnifying-glass icon (in the top-right usually) and then start typing to search in the current folder.

For some people (me) this is much easier that using the command-line.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .