Walk a directory/Recursively: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎{{header|Python}}: A shorter python version)
m (Fixed lang tags.)
Line 7: Line 7:


=={{header|Ada}}==
=={{header|Ada}}==
<lang ada>with Ada.Directories; use Ada.Directories;
<lang ada>
with Ada.Directories; use Ada.Directories;
with Ada.Text_IO;
with Ada.Text_IO;


Line 31: Line 30:
begin
begin
Walk (".", "*.adb");
Walk (".", "*.adb");
end Test_Directory_Walk;
end Test_Directory_Walk;</lang>
</lang>
The solution first enumerates files in a directory, that includes the subdirectories, if their names match the pattern. Then it steps down into each of the subdirectories. The pseudo directories . and .. are excluded. The behavior upon symbolic links depends on the [[OS]] and the implementation of the Ada.Directories package.
The solution first enumerates files in a directory, that includes the subdirectories, if their names match the pattern. Then it steps down into each of the subdirectories. The pseudo directories . and .. are excluded. The behavior upon symbolic links depends on the [[OS]] and the implementation of the Ada.Directories package.
=={{header|ALGOL 68}}==
=={{header|ALGOL 68}}==
Line 38: Line 36:
{{works with|ALGOL 68G|Any - tested with release mk15-0.8b.fc9.i386 - uses non-standard library routines ''get directory'' and'' grep in string''.}}
{{works with|ALGOL 68G|Any - tested with release mk15-0.8b.fc9.i386 - uses non-standard library routines ''get directory'' and'' grep in string''.}}
<!-- {{does not work with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release 1.8.8d.fc9.i386 - ''get directory'' and'' grep in string'' not available in any library ... yet}} -->
<!-- {{does not work with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release 1.8.8d.fc9.i386 - ''get directory'' and'' grep in string'' not available in any library ... yet}} -->
<lang algol>INT match=0, no match=1, out of memory error=2, other error=3;
<lang algol68>INT match=0, no match=1, out of memory error=2, other error=3;


STRING slash = "/", pwd=".", parent="..";
STRING slash = "/", pwd=".", parent="..";
Line 165: Line 163:
{{libheader|boost}}
{{libheader|boost}}


<lang cpp>
<lang cpp>#include "boost/filesystem.hpp"
#include "boost/filesystem.hpp"
#include "boost/regex.hpp"
#include "boost/regex.hpp"
#include <iostream>
#include <iostream>
Line 184: Line 181:
std::cout << iter->path() << "\n";
std::cout << iter->path() << "\n";
}
}
}</lang>
}
</lang>


=={{header|D}}==
=={{header|D}}==
Line 244: Line 240:
=={{header|E}}==
=={{header|E}}==


def walkTree(directory, pattern) {
<lang e>def walkTree(directory, pattern) {
for name => file in directory {
for name => file in directory {
if (name =~ rx`.*$pattern.*`) {
if (name =~ rx`.*$pattern.*`) {
println(file.getPath())
println(file.getPath())
}
}
if (file.isDirectory()) {
if (file.isDirectory()) {
walkTree(file, pattern)
walkTree(file, pattern)
}
}
}
}
}</lang>
}


Example:
Example:


? walkTree(<file:/usr/share/man>, "rmdir")
<lang e>? walkTree(<file:/usr/share/man>, "rmdir")
/usr/share/man/man1/rmdir.1
/usr/share/man/man1/rmdir.1
/usr/share/man/man2/rmdir.2
/usr/share/man/man2/rmdir.2</lang>


=={{header|Forth}}==
=={{header|Forth}}==
Line 266: Line 262:
''Todo: track the full path and print it on matching files.''
''Todo: track the full path and print it on matching files.''


defer ls-filter
<lang forth>defer ls-filter

: dots? ( name len -- ? )
: dots? ( name len -- ? )
dup 1 = if drop c@ [char] . =
dup 1 = if drop c@ [char] . =
else 2 = if dup c@ [char] . = swap 1+ c@ [char] . = and
else 2 = if dup c@ [char] . = swap 1+ c@ [char] . = and
else drop false then then ;
else drop false then then ;

: ls-r ( dir len -- )
: ls-r ( dir len -- )
open-dir if drop exit then ( dirid)
open-dir if drop exit then ( dirid)
begin
begin
dup pad 256 rot read-dir throw
dup pad 256 rot read-dir throw
while
while
pad over dots? 0= if \ ignore current and parent dirs
pad over dots? 0= if \ ignore current and parent dirs
pad over recurse
pad over recurse
pad over ls-filter if
pad over ls-filter if
cr pad swap type
cr pad swap type
else drop then
else drop then
else drop then
else drop then
repeat
repeat
drop close-dir throw ;
drop close-dir throw ;

: c-file? ( str len -- ? )
: c-file? ( str len -- ? )
dup 3 < if 2drop false exit then
dup 3 < if 2drop false exit then
+ 1- dup c@ 32 or
+ 1- dup c@ 32 or
dup [char] c <> swap [char] h <> and if drop false exit then
dup [char] c <> swap [char] h <> and if drop false exit then
1- dup c@ [char] . <> if drop false exit then
1- dup c@ [char] . <> if drop false exit then
drop true ;
drop true ;
' c-file? is ls-filter
' c-file? is ls-filter

s" ." ls-r
s" ." ls-r</lang>


=={{header|Groovy}}==
=={{header|Groovy}}==


Print all text files in the current directory tree
Print all text files in the current directory tree
new File('.').eachFileRecurse {
<lang groovy>new File('.').eachFileRecurse {
if (it.name =~ /.*\.txt/) println it;
if (it.name =~ /.*\.txt/) println it;
}</lang>
}


=={{header|IDL}}==
=={{header|IDL}}==


result = file_search( directory, '*.txt', count=cc )
<lang idl>result = file_search( directory, '*.txt', count=cc )</lang>


This will descend down the directory/ies in the variable <tt>"directory"</tt> (which can be an array) returning an array of strings with the names of the files matching "*.txt" and placing the total number of matches into the variable <tt>"cc"</tt>
This will descend down the directory/ies in the variable <tt>"directory"</tt> (which can be an array) returning an array of strings with the names of the files matching "*.txt" and placing the total number of matches into the variable <tt>"cc"</tt>
Line 312: Line 308:
=={{header|J}}==
=={{header|J}}==


<lang j> require 'dir'
<lang j>require 'dir'
>{."1 dirtree '*.html'
>{."1 dirtree '*.html'</lang>
</lang>


The verb <tt>dirtree</tt> returns a file listing of a directory tree as a boxed matrix with file names in the first column. The primitives <tt>>{."1</tt> will return the unboxed contents of the first column.
The verb <tt>dirtree</tt> returns a file listing of a directory tree as a boxed matrix with file names in the first column. The primitives <tt>>{."1</tt> will return the unboxed contents of the first column.
Line 387: Line 382:
=={{header|Mathematica}}==
=={{header|Mathematica}}==
The built-in function FileNames does exactly this:
The built-in function FileNames does exactly this:
<lang Mathematica>
<lang Mathematica>FileNames[] lists all files in the current working directory.
FileNames[] lists all files in the current working directory.
FileNames[form] lists all files in the current working directory whose names match the string pattern form.
FileNames[form] lists all files in the current working directory whose names match the string pattern form.
FileNames[{form1,form2,...}] lists all files whose names match any of the form_i.
FileNames[{form1,form2,...}] lists all files whose names match any of the form_i.
FileNames[forms,{dir1,dir2,...}] lists files with names matching forms in any of the directories dir_i.
FileNames[forms,{dir1,dir2,...}] lists files with names matching forms in any of the directories dir_i.
FileNames[forms,dirs,n] includes files that are in subdirectories up to n levels down.</lang>
FileNames[forms,dirs,n] includes files that are in subdirectories up to n levels down.
</lang>
Examples (find all files in current directory, find all png files in root directory, find all files on the hard drive):
Examples (find all files in current directory, find all png files in root directory, find all files on the hard drive):
<lang Mathematica>
<lang Mathematica>FileNames["*"]
FileNames["*"]
FileNames["*.png", $RootDirectory]
FileNames["*.png", $RootDirectory]
FileNames["*", {"*"}, Infinity]</lang>
FileNames["*", {"*"}, Infinity]
</lang>
the result can be printed with Print /@ FileNames[....]
the result can be printed with Print /@ FileNames[....]


=={{header|MAXScript}}==
=={{header|MAXScript}}==
fn walkDir dir pattern =
<lang maxscript>fn walkDir dir pattern =
(
(
dirArr = GetDirectories (dir + "\\*")
dirArr = GetDirectories (dir + "\\*")

for d in dirArr do
for d in dirArr do
(
(
join dirArr (getDirectories (d + "\\*"))
join dirArr (getDirectories (d + "\\*"))
)
)

append dirArr (dir + "\\") -- Need to include the original top level directory
append dirArr (dir + "\\") -- Need to include the original top level directory

for f in dirArr do
for f in dirArr do
(
(
print (getFiles (f + pattern))
print (getFiles (f + pattern))
)
)
)
)

walkDir "C:" "*.txt"
walkDir "C:" "*.txt"</lang>


=={{header|Objective-C}}==
=={{header|Objective-C}}==
Line 470: Line 461:
=={{header|Perl}}==
=={{header|Perl}}==
{{works with|Perl|5.x}}
{{works with|Perl|5.x}}
<lang perl> use File::Find qw(find);
<lang perl>use File::Find qw(find);
my $dir = '.';
my $dir = '.';
my $pattern = 'foo';
my $pattern = 'foo';
find sub {print $File::Find::name if /$pattern/}, $dir;</lang>
find sub {print $File::Find::name if /$pattern/}, $dir;</lang>


=={{header|Pop11}}==
=={{header|Pop11}}==
Line 480: Line 471:
trees using shell-like patterns (three dots indicate search for
trees using shell-like patterns (three dots indicate search for
subdirectory tree).
subdirectory tree).
<lang pop11>lvars repp, fil;
<pre>
lvars repp, fil;
;;; create path repeater
;;; create path repeater
sys_file_match('.../*.p', '', false, 0) -> repp;
sys_file_match('.../*.p', '', false, 0) -> repp;
Line 488: Line 478:
;;; print the path
;;; print the path
printf(fil, '%s\n');
printf(fil, '%s\n');
endwhile;
endwhile;</lang>
</pre>


=={{header|Python}}==
=={{header|Python}}==
Line 496: Line 485:
This uses the standard ''os.walk()'' "[[generator]]".
This uses the standard ''os.walk()'' "[[generator]]".


<lang python>
<lang python>import fnmatch
import fnmatch
import os

import os
rootPath = '/'
pattern = '*.mp3' # Can include any UNIX shell-style wildcards
rootPath = '/'
pattern = '*.mp3' # Can include any UNIX shell-style wildcards
for root, dirs, files in os.walk(rootPath):
for root, dirs, files in os.walk(rootPath):
for filename in fnmatch.filter(files, pattern):
for filename in fnmatch.filter(files, pattern):
print os.path.join(root, filename)
print os.path.join(root, filename)</lang>
</lang>


{{works with|Python|<nowiki>2.x</nowiki>}} (deprecated; removed in 3.0)
{{works with|Python|<nowiki>2.x</nowiki>}} (deprecated; removed in 3.0)
Line 512: Line 499:
A more strictly comparable port of this 2.3+ code to earlier versions of Python would be:
A more strictly comparable port of this 2.3+ code to earlier versions of Python would be:


<lang python>
<lang python>from fnmatch import fnmatch
import os, os.path
from fnmatch import fnmatch

import os, os.path
def print_fnmatches(pattern, dir, files):
for filename in files:
def print_fnmatches(pattern, dir, files):
if fnmatch(name, pattern):
for filename in files:
if fnmatch(name, pattern):
print os.path.join(dir, filename)

print os.path.join(dir, filename)
os.path.walk('/', print_fnmatches, '*.mp3')</lang>
os.path.walk('/', print_fnmatches, '*.mp3')</lang>


The old ''os.path.walk'' function was a challenge for many to use because of the need to pass a function into the walk, and any arguments to that function through to it ... as shown. It's sometimes useful to pass mutable objects (lists, dictionaries, or instances of user-defined classes) to the inner function ... for example, to collect all the matching files for later processing.
The old ''os.path.walk'' function was a challenge for many to use because of the need to pass a function into the walk, and any arguments to that function through to it ... as shown. It's sometimes useful to pass mutable objects (lists, dictionaries, or instances of user-defined classes) to the inner function ... for example, to collect all the matching files for later processing.
Line 532: Line 518:
(''Note:'' This uses a non-standard replacement to the '''os.path''' module)
(''Note:'' This uses a non-standard replacement to the '''os.path''' module)


<lang python> from path import path
<lang python>from path import path

rootPath = '/'
rootPath = '/'
pattern = '*.mp3'
pattern = '*.mp3'

d = path(rootPath)
d = path(rootPath)
for f in d.walkfiles(pattern):
for f in d.walkfiles(pattern):
print f</lang>
print f</lang>


=={{header|R}}==
=={{header|R}}==
<lang R>dir("/bar/foo", "mp3",recursive=T)</lang>
<lang R>
dir("/bar/foo", "mp3",recursive=T)
</lang>


=={{header|Ruby}}==
=={{header|Ruby}}==
Pattern matching using regular expressions
Pattern matching using regular expressions
<lang ruby> #define a recursive function that will traverse the directory tree
<lang ruby>#define a recursive function that will traverse the directory tree
def printAndDescend(pattern)
def printAndDescend(pattern)
#we keep track of the directories, to be used in the second, recursive part of this function
#we keep track of the directories, to be used in the second, recursive part of this function
directories=[]
directories=[]
Dir['*'].sort.each do |name|
Dir['*'].sort.each do |name|
if File.file?(name) and name[pattern]
if File.file?(name) and name[pattern]
puts(File.expand_path(name))
puts(File.expand_path(name))
elsif File.directory?(name)
elsif File.directory?(name)
directories << name
directories << name
end
end
directories.each do |name|
#don't descend into . or .. on linux
Dir.chdir(name){printAndDescend(pattern)} if !Dir.pwd[File.expand_path(name)]
end
end
end
end
directories.each do |name|
#print all ruby files
#don't descend into . or .. on linux
printAndDescend(/.+\.rb$/)</lang>
Dir.chdir(name){printAndDescend(pattern)} if !Dir.pwd[File.expand_path(name)]
end
end
#print all ruby files
printAndDescend(/.+\.rb$/)</lang>


Or use the Find core Module
Or use the Find core Module
<lang ruby> require 'find'
<lang ruby>require 'find'

def find_and_print(path, pattern)
def find_and_print(path, pattern)
Find.find(path) do |entry|
Find.find(path) do |entry|
if File.file?(entry) and entry[pattern]
if File.file?(entry) and entry[pattern]
puts entry
puts entry
end
end
end
end
end
end

# print all the ruby files
# print all the ruby files
find_and_print(".", /.+\.rb$/)</lang>
find_and_print(".", /.+\.rb$/)</lang>


Or, to find and print all files under '/foo/bar' the easy way:
Or, to find and print all files under '/foo/bar' the easy way:
Line 588: Line 572:
This is not implemented in the Scala library. Here is a possible solution, building on class ''java.io.File'' and on scala language and library iteration facilities
This is not implemented in the Scala library. Here is a possible solution, building on class ''java.io.File'' and on scala language and library iteration facilities


package io.utils
<lang scala>package io.utils

import java.io.File
/** A wrapper around file, allowing iteration either on direct children
import java.io.File
or on directory tree */
class RichFile(file: File) {
def children = new Iterable[File] {
/** A wrapper around file, allowing iteration either on direct children
def elements =
or on directory tree */
if (file.isDirectory) file.listFiles.elements else Iterator.empty;
class RichFile(file: File) {
}

def children = new Iterable[File] {
def elements =
def andTree : Iterable[File] = (
Seq.single(file)
if (file.isDirectory) file.listFiles.elements else Iterator.empty;
++ children.flatMap(child => new RichFile(child).andTree))
}
}
/** implicitely enrich java.io.File with methods of RichFile */
def andTree : Iterable[File] = (
object RichFile {
Seq.single(file)
++ children.flatMap(child => new RichFile(child).andTree))
implicit def toRichFile(file: File) = new RichFile(file)
}</lang>
}
/** implicitely enrich java.io.File with methods of RichFile */
object RichFile {
implicit def toRichFile(file: File) = new RichFile(file)
}


Class ''RichFile'' gets a ''java.io.File'' in constructor. Its two methods return ''Iterable''s on items of type File. ''children'' allow iterations on the direct children (empty if file is not a directory). ''andTree'' contains a file and all files below, as a concatenation (''++'') of a sequence which contains only a file (''Seq.single'') and actual descendants. The method ''flatMap'' in Iterable takes a function argument which associates each item (''child'') to another Iterable (''andTree'' called recursively on that child) and returns the concatenation of those iterables.
Class ''RichFile'' gets a ''java.io.File'' in constructor. Its two methods return ''Iterable''s on items of type File. ''children'' allow iterations on the direct children (empty if file is not a directory). ''andTree'' contains a file and all files below, as a concatenation (''++'') of a sequence which contains only a file (''Seq.single'') and actual descendants. The method ''flatMap'' in Iterable takes a function argument which associates each item (''child'') to another Iterable (''andTree'' called recursively on that child) and returns the concatenation of those iterables.
Line 616: Line 600:


Using it :
Using it :
package test.io.utils
<lang scala>package test.io.utils

import io.utils.RichFile._ // this makes implicit toRichFile active
import io.utils.RichFile._ // this makes implicit toRichFile active
import java.io.File
import java.io.File

object Test extends Application {
object Test extends Application {
val root = new File("/home/user")
val root = new File("/home/user")
for(f <- root.andTree) Console.println(f)
for(f <- root.andTree) Console.println(f)

// filtering comes for free
// filtering comes for free
for(f <- root.andTree; if f.getName.endsWith(".mp3")) Console.println(f)
for(f <- root.andTree; if f.getName.endsWith(".mp3")) Console.println(f)
}</lang>
}


=={{header|Smalltalk}}==
=={{header|Smalltalk}}==
Line 684: Line 668:
This uses the OS pattern matching
This uses the OS pattern matching


Sub walkTree(ByVal directory As IO.DirectoryInfo, ByVal pattern As String)
<lang vbnet>Sub walkTree(ByVal directory As IO.DirectoryInfo, ByVal pattern As String)
For Each file In directory.GetFiles(pattern)
For Each file In directory.GetFiles(pattern)
Console.WriteLine(file.FullName)
Console.WriteLine(file.FullName)
Next
Next
For Each subDir In directory.GetDirectories
For Each subDir In directory.GetDirectories
walkTree(subDir, pattern)
walkTree(subDir, pattern)
Next
Next
End Sub
End Sub</lang>


=={{header|UNIX Shell}}==
=={{header|UNIX Shell}}==
Line 758: Line 742:
=={{header|UnixPipes}}==
=={{header|UnixPipes}}==
Find accepts file globbing params too as -name, here I use regexp from grep.
Find accepts file globbing params too as -name, here I use regexp from grep.
find . | grep '.*\.txt$'
<lang bash>find . | grep '.*\.txt$'</lang>


{{omit from|TI-89 BASIC}} <!-- Does not have a filesystem, just namespaced variables, which can't be listed from a program. -->
{{omit from|TI-89 BASIC}} <!-- Does not have a filesystem, just namespaced variables, which can't be listed from a program. -->

Revision as of 17:32, 22 November 2009

Task
Walk a directory/Recursively
You are encouraged to solve this task according to the task description, using any language you may know.

Walk a given directory tree and print files matching a given pattern.

Note: Please be careful when running any code examples found here.

Ada

<lang ada>with Ada.Directories; use Ada.Directories; with Ada.Text_IO;

procedure Test_Directory_Walk is

  procedure Walk (Name : String; Pattern : String) is
     procedure Print (Item : Directory_Entry_Type) is
     begin
        Ada.Text_IO.Put_Line (Full_Name (Item));
     end Print;
     procedure Walk (Item : Directory_Entry_Type) is
     begin
        if Simple_Name (Item) /= "." and then Simple_Name (Item) /= ".." then
           Walk (Full_Name (Item), Pattern);
        end if;
     exception
        when Name_Error => null;
     end Walk;
  begin
     Search (Name, Pattern, (others => True), Print'Access);
     Search (Name, "", (Directory => True, others => False), Walk'Access);
  end Walk;

begin

  Walk (".", "*.adb");

end Test_Directory_Walk;</lang> The solution first enumerates files in a directory, that includes the subdirectories, if their names match the pattern. Then it steps down into each of the subdirectories. The pseudo directories . and .. are excluded. The behavior upon symbolic links depends on the OS and the implementation of the Ada.Directories package.

ALGOL 68

Works with: ALGOL 68G version Any - tested with release mk15-0.8b.fc9.i386 - uses non-standard library routines get directory and grep in string.

<lang algol68>INT match=0, no match=1, out of memory error=2, other error=3;

STRING slash = "/", pwd=".", parent="..";

PROC walk tree = (STRING path, PROC (STRING)VOID call back)VOID: (

 []STRING files = get directory(path);
 FOR file index TO UPB files DO
   STRING file = files[file index];
   STRING path file = path+slash+file;
   IF file is directory(path file) THEN
     IF file NE pwd AND file NE parent THEN
       walk tree(path file, call back)
     FI
   ELSE
     call back(path file)
   FI
 OD

);

STRING re sort a68 = "[Ss]ort[^/]*[.]a68$";

PROC match sort a68 and print = (STRING path file)VOID:

 IF grep in string(re sort a68, path file, NIL, NIL) = match THEN
   print((path file, new line))
 FI;

walk tree(".", match sort a68 and print)</lang> Sample Output:

./Shell_sort_c.a68
./Quick_sort.a68
./Shell_sort.a68
./Cocktail_Sort.a68
./Selection_Sort.a68
./Merge_sort.a68
./tmp/test_sort.a68
./Bobosort.a68
./Sorting_an_Array_of_Integers.a68
./Insertion_Sort.a68
./Permutation_Sort.a68

AutoHotkey

Display all TMP files in Temp directory and its subdirectories. <lang autohotkey>Loop, %A_Temp%\*.tmp,,1

out .= A_LoopFileName "`n"

MsgBox,% out</lang>

C

Works with: POSIX version .1-2001

This is a (recursive) extension of the code at Walk Directory. <lang c>#include <sys/types.h>

  1. include <sys/stat.h>
  2. include <unistd.h>
  3. include <dirent.h>
  4. include <regex.h>
  5. include <stdio.h>
  1. define MAXPD 1024

void walker(const char *dir, const char *pattern) {

   struct dirent *entry;
   regex_t reg;
   DIR *d;
   struct stat fs;
   static int indent = 0;
   int i;
   char pd[MAXPD];
   if (regcomp(&reg, pattern, REG_EXTENDED | REG_NOSUB)) return;
   if (!(d = opendir(dir))) return;
   while (entry = readdir(d)) {
     if ( ( strcmp(".", entry->d_name) == 0 ) ||
          ( strcmp("..", entry->d_name) == 0 ) ) continue;
     if ( stat(entry->d_name, &fs) < 0 ) return;
     if ( S_ISDIR(fs.st_mode) ) {

for(i=0; i < indent; i++) printf(" "); puts(entry->d_name); indent += 2; if ( getcwd(pd, MAXPD) == NULL ) return; if ( chdir(entry->d_name) < 0 ) return; walker(".", pattern); if ( chdir(pd) < 0 ) return; indent -= 2;

     } else {

if (!regexec(&reg, entry->d_name, 0, NULL, 0)) { for(i=0; i < indent; i++) printf(" "); puts(entry->d_name); }

     }
   }
   closedir(d);

}

int main() {

   walker(".", ".\\.c$");
   return 0;

}</lang>

Common Lisp

Library: CL-FAD

This example uses the CL-FAD library to achieve compatibility where the ANSI CL standard leaves ambiguities about pathnames.

<lang lisp>(defun mapc-directory-tree (fn directory)

 (dolist (entry (cl-fad:list-directory directory))
   (when (cl-fad:directory-pathname-p entry)
     (mapc-directory-tree fn entry))
   (funcall fn entry)))</lang>

<lang lisp>CL-USER> (mapc-directory-tree (lambda (x)

                               (when (equal (pathname-type x) "lisp")
                                 (write-line (namestring x))))
                             "lang/")

/home/sthalik/lang/lisp/.#bitmap.lisp /home/sthalik/lang/lisp/avg.lisp /home/sthalik/lang/lisp/bitmap.lisp /home/sthalik/lang/lisp/box-muller.lisp /home/sthalik/lang/lisp/displaced-subseq.lisp [...]</lang>

C++

Library: boost

<lang cpp>#include "boost/filesystem.hpp"

  1. include "boost/regex.hpp"
  2. include <iostream>

using namespace boost::filesystem;

int main() {

 path current_dir("."); //
 boost::regex pattern("a.*"); // list all files starting with a
 for (recursive_directory_iterator iter(current_dir), end;
      iter != end;
      ++iter)
 {
   std::string name = iter->path().leaf();
   if (regex_match(name, pattern))
     std::cout << iter->path() << "\n";
 }

}</lang>

D

module std.file provides different walk directory functions (listdir).
This one recursively walks the directory, which can either match by regular expression or unix shell style pattern. <lang d>import std.stdio; import std.file; import std.regexp;

void main(string[] args) {

 auto path = args.length > 1 ? args[1] : "." ; // default current 
 auto pattern = args.length > 2 ? args[2] : "*.*"; // default all file 		
 bool useRegExp = (args.length > 3 && args[3] == "-re") ; // pattern matching method
 if (args.length > 3 && args[3] == "-re")
   // use Regular Expression 
   foreach (d; listdir(path, RegExp(pattern)))
     writefln(d);
 else 
  // use unix shell style	pattern matching
  foreach (d; listdir(path, pattern))
    writefln(d);							
}</lang>

This one does not itself walk into a sub directory, but can be recursive by a callback delegate function. <lang d>import std.stdio; import std.file; import std.regexp; import std.path ;

void main(string[] args) {

 auto path = args.length > 1 ? args[1] : "." ; // default current 
 auto pattern = args.length > 2 ? args[2] : "*.*"; // default all file     
 bool useRegExp = (args.length > 3 && args[3] == "-re") ; // pattern matching method
 bool recursive = (args.length <= 4 || args[4] != "-nr") ; // recursive?
 bool matchNPrint(DirEntry* de) {
   bool bPrint = false ;
   if(!de.isdir) {
     if(useRegExp){
       if(search(de.name, pattern)) // this _search_ from regexp module
         writefln(de.name) ;
     }else{
       if(fnmatch(de.name, pattern)) // this _fnmatch_ from path module
         writefln(de.name) ;
     }
   } else
     if(recursive)
       listdir(de.name, &matchNPrint) ; // recursive sub dir
   return true ; // continue 
 }
 
 listdir(path, &matchNPrint) ;
}</lang>

DOS Batch File

<lang dos>dir /a-d %1</lang>

E

<lang e>def walkTree(directory, pattern) {

 for name => file in directory {
   if (name =~ rx`.*$pattern.*`) {
     println(file.getPath())
   }
   if (file.isDirectory()) {
     walkTree(file, pattern)
   }
 }

}</lang>

Example:

<lang e>? walkTree(<file:/usr/share/man>, "rmdir") /usr/share/man/man1/rmdir.1 /usr/share/man/man2/rmdir.2</lang>

Forth

Works with: gforth version 0.6.2

Todo: track the full path and print it on matching files.

<lang forth>defer ls-filter

dots? ( name len -- ? )
 dup 1 = if drop c@ [char] . =
 else 2 = if dup c@ [char] . = swap 1+ c@ [char] . = and
 else drop false then then ;
ls-r ( dir len -- )
 open-dir if drop exit then  ( dirid)
 begin
   dup pad 256 rot read-dir throw
 while
   pad over dots? 0= if   \ ignore current and parent dirs
     pad over recurse
     pad over ls-filter if
       cr pad swap type
     else drop then
   else drop then 
 repeat
 drop close-dir throw ;
c-file? ( str len -- ? )
 dup 3 < if 2drop false exit then
 + 1- dup c@ 32 or
  dup [char] c <> swap [char] h <> and if drop false exit then
 1- dup c@ [char] . <> if drop false exit then
 drop true ;

' c-file? is ls-filter

s" ." ls-r</lang>

Groovy

Print all text files in the current directory tree <lang groovy>new File('.').eachFileRecurse {

 if (it.name =~ /.*\.txt/) println it;

}</lang>

IDL

<lang idl>result = file_search( directory, '*.txt', count=cc )</lang>

This will descend down the directory/ies in the variable "directory" (which can be an array) returning an array of strings with the names of the files matching "*.txt" and placing the total number of matches into the variable "cc"

J

<lang j>require 'dir' >{."1 dirtree '*.html'</lang>

The verb dirtree returns a file listing of a directory tree as a boxed matrix with file names in the first column. The primitives >{."1 will return the unboxed contents of the first column.

Java

Works with: Java version 1.4+

Done using no pattern. But with end string comparison which gave better results.

<lang java>import java.io.File; public class MainEntry {

   public static void main(String[] args) {
       walkin(new File("/home/user")); //Replace this with a suitable directory
   }
   
   /**
    * Recursive function to descend into the directory tree and find all the files 
    * that end with ".mp3"
    * @param dir A file object defining the top directory
    **/
   public static void walkin(File dir) {
       String pattern = ".mp3";
       
       File listFile[] = dir.listFiles();
       if(listFile != null) {
           for(int i=0; i<listFile.length; i++) {
               if(listFile[i].isDirectory()) {
                   walkin(listFile[i]);
               } else {
                   if(listFile[i].getName().endsWith(pattern)) {
                       System.out.println(listFile[i].getPath());
                   }
               }
           }
       }
   }

}</lang>

JavaScript

Works with: JScript

<lang javascript>var fso = new ActiveXObject("Scripting.FileSystemObject");

function walkDirectoryTree(folder, folder_name, re_pattern) {

   WScript.Echo("Files in " + folder_name + " matching '" + re_pattern + "':");
   walkDirectoryFilter(folder.files, re_pattern);
   var subfolders = folder.SubFolders;
   WScript.Echo("Folders in " + folder_name + " matching '" + re_pattern + "':");
   walkDirectoryFilter(subfolders, re_pattern);
   WScript.Echo();
   var en = new Enumerator(subfolders);
   while (! en.atEnd()) {
       var subfolder = en.item();
       walkDirectoryTree(subfolder, folder_name + "/" + subfolder.name, re_pattern);
       en.moveNext();
   }

}

function walkDirectoryFilter(items, re_pattern) {

   var e = new Enumerator(items);
   while (! e.atEnd()) {
       var item = e.item();
       if (item.name.match(re_pattern))
           WScript.Echo(item.name);
       e.moveNext();
   }

}

walkDirectoryTree(dir, dir.name, '\\.txt$');</lang>

Mathematica

The built-in function FileNames does exactly this: <lang Mathematica>FileNames[] lists all files in the current working directory. FileNames[form] lists all files in the current working directory whose names match the string pattern form. FileNames[{form1,form2,...}] lists all files whose names match any of the form_i. FileNames[forms,{dir1,dir2,...}] lists files with names matching forms in any of the directories dir_i. FileNames[forms,dirs,n] includes files that are in subdirectories up to n levels down.</lang> Examples (find all files in current directory, find all png files in root directory, find all files on the hard drive): <lang Mathematica>FileNames["*"] FileNames["*.png", $RootDirectory] FileNames["*", {"*"}, Infinity]</lang> the result can be printed with Print /@ FileNames[....]

MAXScript

<lang maxscript>fn walkDir dir pattern = (

   dirArr = GetDirectories (dir + "\\*")
   for d in dirArr do
   (
       join dirArr (getDirectories (d + "\\*"))
   )
   append dirArr (dir + "\\") -- Need to include the original top level directory
   for f in dirArr do
   (
       print (getFiles (f + pattern))
   )

)

walkDir "C:" "*.txt"</lang>

Objective-C

<lang objc>NSString *dir = NSHomeDirectory(); NSDirectoryEnumerator *de = [[NSFileManager defaultManager] enumeratorAtPath:dir];

NSString *file; while ((file = [de nextObject]))

 if ([[file pathExtension] isEqualToString:@"mp3"])
   NSLog(@"%@", file);</lang>

OCaml

<lang ocaml>#!/usr/bin/env ocaml

  1. load "unix.cma"
  2. load "str.cma"

open Unix

let walk_directory_tree dir pattern =

 let select str = Str.string_match (Str.regexp pattern) str 0 in
 let rec walk dir =
   let contents = Array.to_list (Sys.readdir dir) in
   let contents = List.rev_map (Filename.concat dir) contents in
   let dirs, files =
     List.fold_left (fun (dirs,files) f ->
          match (stat f).st_kind with
          | S_REG -> (dirs, f::files)  (* Regular file *)
          | S_DIR -> (f::dirs, files)  (* Directory *)
          | _ -> (dirs, files)
       ) ([],[]) contents
   in
   let matched = List.filter (select) files in
   (* recursively walk into sub-directories: *)
   let results =
     List.fold_left (fun acc dir ->
       let sub_result = walk dir in
       List.rev_append sub_result acc
     ) matched dirs
   in
   (results)
 in
 walk dir

let () =

 let results = walk_directory_tree "/usr/local/lib/ocaml"  ".*\\.cma" in
 List.iter print_endline results;
</lang>

Perl

Works with: Perl version 5.x

<lang perl>use File::Find qw(find); my $dir = '.'; my $pattern = 'foo'; find sub {print $File::Find::name if /$pattern/}, $dir;</lang>

Pop11

Built-in procedure sys_file_match searches directories or directory trees using shell-like patterns (three dots indicate search for subdirectory tree). <lang pop11>lvars repp, fil;

create path repeater

sys_file_match('.../*.p', , false, 0) -> repp;

iterate over paths

while (repp() ->> fil) /= termin do

    ;;; print the path
    printf(fil, '%s\n');

endwhile;</lang>

Python

Works with: Python version 2.3+

This uses the standard os.walk() "generator".

<lang python>import fnmatch import os

rootPath = '/' pattern = '*.mp3' # Can include any UNIX shell-style wildcards

for root, dirs, files in os.walk(rootPath):

   for filename in fnmatch.filter(files, pattern):
           print os.path.join(root, filename)</lang>
Works with: Python version 2.x

(deprecated; removed in 3.0)

A more strictly comparable port of this 2.3+ code to earlier versions of Python would be:

<lang python>from fnmatch import fnmatch import os, os.path

def print_fnmatches(pattern, dir, files):

   for filename in files:
       if fnmatch(name, pattern):
           print os.path.join(dir, filename)

os.path.walk('/', print_fnmatches, '*.mp3')</lang>

The old os.path.walk function was a challenge for many to use because of the need to pass a function into the walk, and any arguments to that function through to it ... as shown. It's sometimes useful to pass mutable objects (lists, dictionaries, or instances of user-defined classes) to the inner function ... for example, to collect all the matching files for later processing.

Of course the function being passed down through os.path.walk() can also be an instance of an object which maintains it's own data collections. Any matching criteria can be set as attributes of that object in advance and methods of that object can be called upon for later processing as well. That would the an object oriented approach which would obviate the need for the "arguments" to be passed through os.path.walk() at all.

Works with: Python version 2.5
Library: Path

(Note: This uses a non-standard replacement to the os.path module)

<lang python>from path import path

rootPath = '/' pattern = '*.mp3'

d = path(rootPath) for f in d.walkfiles(pattern):

 print f</lang>

R

<lang R>dir("/bar/foo", "mp3",recursive=T)</lang>

Ruby

Pattern matching using regular expressions <lang ruby>#define a recursive function that will traverse the directory tree def printAndDescend(pattern)

 #we keep track of the directories, to be used in the second, recursive part of this function
 directories=[]
 Dir['*'].sort.each do |name|
   if File.file?(name) and name[pattern]
     puts(File.expand_path(name))
   elsif File.directory?(name)
     directories << name
   end
 end
 directories.each do |name|
   #don't descend into . or .. on linux
   Dir.chdir(name){printAndDescend(pattern)} if !Dir.pwd[File.expand_path(name)]
 end

end

  1. print all ruby files

printAndDescend(/.+\.rb$/)</lang>

Or use the Find core Module

<lang ruby>require 'find'

def find_and_print(path, pattern)

 Find.find(path) do |entry|
   if File.file?(entry) and entry[pattern]
     puts entry
   end
 end

end

  1. print all the ruby files

find_and_print(".", /.+\.rb$/)</lang>

Or, to find and print all files under '/foo/bar' the easy way: <lang ruby> Dir.glob( File.join('/foo/bar', '**', '*') ) { |file| puts file }</lang>

Scala

This is not implemented in the Scala library. Here is a possible solution, building on class java.io.File and on scala language and library iteration facilities

<lang scala>package io.utils

import java.io.File

/** A wrapper around file, allowing iteration either on direct children

    or on directory tree */

class RichFile(file: File) {

 def children = new Iterable[File] {
   def elements = 
     if (file.isDirectory) file.listFiles.elements else Iterator.empty;
 }
 def andTree : Iterable[File] = (
   Seq.single(file) 
   ++ children.flatMap(child => new RichFile(child).andTree))

}

/** implicitely enrich java.io.File with methods of RichFile */ object RichFile {

 implicit def toRichFile(file: File) = new RichFile(file)

}</lang>

Class RichFile gets a java.io.File in constructor. Its two methods return Iterables on items of type File. children allow iterations on the direct children (empty if file is not a directory). andTree contains a file and all files below, as a concatenation (++) of a sequence which contains only a file (Seq.single) and actual descendants. The method flatMap in Iterable takes a function argument which associates each item (child) to another Iterable (andTree called recursively on that child) and returns the concatenation of those iterables.

The purpose of the object RichFile is to publish the implicit method toRichFile. When this method is available in scope (after import RichFile.toRichFile or import RichFile._), it is called behind the scene when a method of class RichFile is called on an instance of type File : with f of type File, code f.children (resp. f.andTree) becomes toRichFile(f).children (resp. toRichFile(f).andTree). It is as if class File had been added the methods of class RichFile.

Using it : <lang scala>package test.io.utils

import io.utils.RichFile._ // this makes implicit toRichFile active import java.io.File

object Test extends Application {

 val root = new File("/home/user")
 for(f <- root.andTree) Console.println(f)
// filtering comes for free
for(f <- root.andTree; if f.getName.endsWith(".mp3")) Console.println(f)

}</lang>

Smalltalk

Works with: GNU Smalltalk

<lang smalltalk>Directory extend [

 wholeContent: aPattern do: twoBlock [ 
   self wholeContent: aPattern withLevel: 0 do: twoBlock.
 ]
 wholeContent: aPattern withLevel: l do: twoBlock [
   |cont|
   cont := (self contents) asSortedCollection.
   cont remove: '.'; remove: '..'.
   cont
   do: [ :n | |fn ps|
     ps := (Directory pathSeparator) asString.
     fn := (self name), ps, n. 
     ((File name: fn) isDirectory)
     ifTrue: [
       twoBlock value: (n, ps) value: l.

(Directory name: fn) wholeContent: aPattern withLevel: (l+1) do: twoBlock.

     ]
     ifFalse: [
       ( n =~ aPattern )
       ifMatched: [ :m |
         twoBlock value: n value: l
       ]
     ]
   ]
 ]

].</lang>

<lang smalltalk>|d| d := Directory name: '.'. d wholeContent: '\.st$' do: [ :f :l |

  0 to: l do: [ :i | (Character tab) display ].
  f displayNl

].</lang>

Tcl

Works with: Tcl version 8.4

<lang tcl>proc walkin {fromDir pattern} {

   foreach fname [glob -nocomplain -directory $fromDir *] {
       if {[file isdirectory $fname]} {
           walkin $fname $pattern
       } elseif {[string match $pattern [file tail $fname]]} {
           puts [file normalize $fname]
       }
   }

}

  1. replace directory with something appropriate

walkin /home/user *.mp3</lang>

Visual Basic .NET

Works with: Visual Basic .NET version 9.0+

This uses the OS pattern matching

<lang vbnet>Sub walkTree(ByVal directory As IO.DirectoryInfo, ByVal pattern As String)

   For Each file In directory.GetFiles(pattern)
       Console.WriteLine(file.FullName)
   Next
   For Each subDir In directory.GetDirectories
       walkTree(subDir, pattern)
   Next

End Sub</lang>

UNIX Shell

Works with: Bourne Again SHell

<lang bash>#! /bin/bash

indent_print() {

   for((i=0; i < $1; i++)); do

echo -ne "\t"

   done
   echo "$2"

}

walk_tree() {

   local oldifs bn lev pr pmat
   if $# -lt 3 ; then

if $# -lt 2 ; then pmat=".*" else pmat="$2" fi walk_tree "$1" "$pmat" 0 return

   fi
   lev=$3
   [ -d "$1" ] || return
   oldifs=$IFS
   IFS="

"

   for el in $1/*; do

bn=$(basename "$el") if -d "$el" ; then indent_print $lev "$bn/" pr=$( walk_tree "$el" "$2" $(( lev + 1)) ) echo "$pr" else if "$bn" =~ $2 ; then indent_print $lev "$bn" fi fi

   done
   IFS=$oldifs

}

walk_tree "$1" "\.sh$"</lang>

A simplified version that gives the same output:

<lang bash>#! /usr/bin/env bash

walk_tree() { ls "$1" | while IFS= read i; do if [ -d "$1/$i" ]; then echo "$i/" walk_tree "$1/$i" "$2" | sed -r 's/^/\t/' else echo "$i" | grep -E "$2" fi done }

walk_tree "$1" "\.sh$"</lang>

UnixPipes

Find accepts file globbing params too as -name, here I use regexp from grep. <lang bash>find . | grep '.*\.txt$'</lang>