Walk a directory/Recursively: Difference between revisions
Content deleted Content added
→{{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 |
<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}}== |
||
<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: |
Example: |
||
<lang e>? walkTree(<file:/usr/share/man>, "rmdir") |
|||
/usr/share/man/man1/rmdir.1 |
|||
/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.'' |
||
<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> |
|||
=={{header|Groovy}}== |
=={{header|Groovy}}== |
||
Print all text files in the current directory tree |
Print all text files in the current directory tree |
||
<lang groovy>new File('.').eachFileRecurse { |
|||
if (it.name =~ /.*\.txt/) println it; |
|||
}</lang> |
|||
} |
|||
=={{header|IDL}}== |
=={{header|IDL}}== |
||
<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> |
<lang j>require 'dir' |
||
>{."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[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> |
|||
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["*.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}}== |
||
<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> |
|||
=={{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> |
<lang perl>use File::Find qw(find); |
||
my $dir = '.'; |
|||
my $pattern = 'foo'; |
|||
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 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 filename in fnmatch.filter(files, pattern): |
|||
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: |
|||
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> |
<lang python>from path import path |
||
rootPath = '/' |
|||
pattern = '*.mp3' |
|||
d = path(rootPath) |
|||
for f in d.walkfiles(pattern): |
|||
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> |
<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 |
||
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> |
<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 |
||
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 |
||
<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 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) |
|||
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 : |
||
<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> |
|||
} |
|||
=={{header|Smalltalk}}== |
=={{header|Smalltalk}}== |
||
Line 684: | Line 668: | ||
This uses the OS pattern matching |
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> |
|||
=={{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. |
||
<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. --> |