Walk a directory/Recursively: Difference between revisions
No edit summary |
|||
Line 76: | Line 76: | ||
} |
} |
||
} |
} |
||
==[[Pop11]]== |
|||
[[Category:Pop11]] |
|||
Builtion 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; |
|||
;;; print iterate over paths |
|||
while (repp() ->> fil) /= termin do |
|||
;;; print the path |
|||
printf(fil, '%s\n'); |
|||
endwhile; |
|||
==[[Python]]== |
==[[Python]]== |
Revision as of 20:10, 14 May 2007
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.
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
Compiler: javac, JDK 1.4 and up
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()); } } } } } }
Perl
Interpreter: Perl 5.x
$ARGV[0] and [1] are parameters provided from the command line.
dig($ARGV[0], $ARGV[1]) if (-d $ARGV[0]); sub dig($;$$){ my $dir = shift; my $pat = shift or undef; my $lvl = shift || 1; return if (!-d $dir or $lvl > 1000); # quit if not a dir or we are too deep $dir =~ s/\/?$/\//; # add trailing slash # get dirs and files under this dir opendir(DIR, $dir); my @files = grep(!/^\.{1,2}$/, readdir(DIR)); closedir(DIR); # alphabetically sort then dig deeper or print the file for (sort { lc($a) cmp lc($b) } (@files)){ # skip if its not a file or dir, or it doesnt match the pattern if provided next if ((!-d $dir . $_ and !-f $dir . $_) or ($pat and -f $dir . $_ and $_ !~ /$pat/)); (-d $dir . $_) ? dig($dir . $_, $pat, $lvl + 1) : (print "$dir$_\n"); } }
Pop11
Builtion 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; ;;; print iterate over paths while (repp() ->> fil) /= termin do ;;; print the path printf(fil, '%s\n'); endwhile;
Python
Interpreter: Python 2.5
import fnmatch import os rootPath = '/' # Change to a suitable path for your OS pattern = '*.mp3' # Any string; Can include any UNIX shell-style wildcards # Includes: *, ?, [seq], [!seq] for root, directories, files in os.walk(rootPath): for aFile in files: if fnmatch.fnmatch(aFile, pattern): print os.path.join(root, aFile)
Interpreter: Python 2.5
Libraries: Path
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$/)
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(val f <- root.andTree) Console.println(f) // filtering comes for free for(val f <- root.andTree; f.getName.endsWith(".mp3")) Console.println(f) }
Tcl
Interpreter: Tcl 8.4
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