Walk a directory/Recursively: Difference between revisions
m (Changed over to works with template) |
|||
Line 79: | Line 79: | ||
=={{header|Forth}}== |
=={{header|Forth}}== |
||
{{works with|gforth|0.6.2}} |
|||
''Todo: track the full path and print it on matching files.'' |
''Todo: track the full path and print it on matching files.'' |
||
Line 129: | Line 128: | ||
=={{header|Java}}== |
=={{header|Java}}== |
||
{{works with|Java|1.4+}} |
|||
Done using no pattern. But with end string comparison which gave better results. |
Done using no pattern. But with end string comparison which gave better results. |
||
Line 183: | Line 181: | ||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
{{works with|Perl|5.x}} |
|||
use File::Find qw(find); |
use File::Find qw(find); |
||
my $dir = '.'; |
my $dir = '.'; |
||
Line 208: | Line 205: | ||
=={{header|Python}}== |
=={{header|Python}}== |
||
{{works with|Python|2.5}} |
|||
This uses the standard ''os.walk()'' "[[generator]]". |
This uses the standard ''os.walk()'' "[[generator]]". |
||
Line 223: | Line 219: | ||
print os.path.join(root, filename) |
print os.path.join(root, filename) |
||
{{works with|Python|<nowiki><2.2</nowiki>}} |
|||
'''Interpreter:''' [[Python]] older then 2.2 |
|||
A more strictly comparable port of this 2.5 code to earlier versions of Python would be: |
A more strictly comparable port of this 2.5 code to earlier versions of Python would be: |
||
Line 237: | Line 232: | ||
os.path.walk('/', print_fnmatches, '*.mp3') |
os.path.walk('/', print_fnmatches, '*.mp3') |
||
{{works with|Python|2.5}} |
|||
{{libheader|Path}} |
{{libheader|Path}} |
||
(''Note:'' This uses a non-standard replacement to the '''os.path''' module) |
(''Note:'' This uses a non-standard replacement to the '''os.path''' module) |
||
Line 316: | Line 310: | ||
} |
} |
||
Class ''RichFile'' gets a ''java.io.File'' in constructor. Its two methods returns ''Iterable''s on items of type File. ''children'' allow iterations on the direct children (empty if file is not a directory). |
Class ''RichFile'' gets a ''java.io.File'' in constructor. Its two methods returns ''Iterable''s on items of type File. ''children'' allow iterations on the direct children (empty if file is not a directory). ''andTree'' contains file and all files below, as a concatenation (''++'') of a a sequence which contains only file (''Seq.single'') and actual descendants. 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 object ''RichFile'' is to publish 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. |
The purpose of object ''RichFile'' is to publish 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. |
||
Line 336: | Line 330: | ||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
{{works with|Tcl|8.4}} |
|||
'''Interpreter:''' [[Tcl]] 8.4 |
|||
proc walkin { fromDir } { |
proc walkin { fromDir } { |
||
foreach fname [glob -nocomplain -directory $fromDir *] { |
foreach fname [glob -nocomplain -directory $fromDir *] { |
||
Line 356: | Line 350: | ||
'''Platform:''' [[.NET]] |
'''Platform:''' [[.NET]] |
||
{{works with|Visual Basic .NET|9.0+}} |
|||
'''Language Version:''' 9.0+ |
|||
This uses the OS pattern matching |
This uses the OS pattern matching |
||
Revision as of 02:50, 19 February 2008
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.
D
module std.file provide different walk directory functions (listdir).
This one recursively walk the directory, which can either match by regular expression or unix shell style pattern.
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); }
This one does not itself walk into sub directory, but can be recursive by a callback delegate function.
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) ; }
E
def walkTree(directory, pattern) { for name => file in directory { if (name =~ rx`.*$pattern.*`) { println(file.getPath()) } if (file.isDirectory()) { walkTree(file, pattern) } } }
Example:
? walkTree(<file:/usr/share/man>, "rmdir") /usr/share/man/man1/rmdir.1 /usr/share/man/man2/rmdir.2
Forth
Todo: track the full path and print it on matching files.
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
Groovy
Print all text files in the current directory tree
new File('.').eachFileRecurse { if (it.name =~ /.*\.txt/) println it; }
IDL
result = file_search( directory, '*.txt', count=cc )
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"
Java
Done using no pattern. But with end string comparison which gave better results.
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 descent into the directory tree and find all the file * 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()); } } } } } }
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"
Perl
use File::Find qw(find); my $dir = '.'; my $pattern = 'foo'; find sub {print $File::Find::name if /$pattern/}, $dir;
Pop11
Builtin procedure sys_file_match searches directories or directory trees using shell-like patterns (three dots indicate search for subdirectory tree).
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;
Python
This uses the standard os.walk() "generator".
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 files: if fnmatch.fnmatch(filename, pattern): print os.path.join(root, filename)
A more strictly comparable port of this 2.5 code to earlier versions of Python would be:
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')
(Note: This uses a non-standard replacement to the os.path module)
from path import path rootPath = '/' pattern = '*.mp3' d = path(rootPath) for f in d.walkfiles(pattern): print f
Ruby
Pattern matching using regular expressions
#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 #print all ruby files printAndDescend(/.+\.rb$/)
Or use the Find core Module
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 # print all the ruby files find_and_print(".", /.+\.rb$/)
Or, to find and print all files under '/foo/bar' the easy way:
Dir.glob( File.join('/foo/bar', '**', '*') ) { |file| puts file }
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
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) }
Class RichFile gets a java.io.File in constructor. Its two methods returns Iterables on items of type File. children allow iterations on the direct children (empty if file is not a directory). andTree contains file and all files below, as a concatenation (++) of a a sequence which contains only file (Seq.single) and actual descendants. 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 object RichFile is to publish 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 :
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) }
Tcl
proc walkin { fromDir } { foreach fname [glob -nocomplain -directory $fromDir *] { if { [file isdirectory $fname] } { walkin $fname } else { if { [string match *.mp3 $fname] } { puts [file normalize $fname] } } } } # replace directory with something appropriate walkin /home/user
Visual Basic .NET
Platform: .NET
This uses the OS pattern matching
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