1 package Path::Class::Dir;
7 use Path::Class::Entity;
9 use base qw(Path::Class::Entity);
15 my $self = shift->SUPER::new();
17 # If the only arg is undef, it's probably a mistake. Without this
18 # special case here, we'd return the root directory, which is a
19 # lousy thing to do to someone when they made a mistake. Return
21 return if @_==1 && !defined($_[0]);
25 my $first = (@_ == 0 ? $s->curdir :
26 $_[0] eq '' ? (shift, $s->rootdir) :
30 ($self->{volume}, my $dirs) = $s->splitpath( $s->canonpath($first) , 1);
31 $self->{dirs} = [$s->splitdir($s->catdir($dirs, @_))];
39 my ($self, $type) = @_;
42 local $self->{file_spec_class} = $self->_spec_class($type);
46 # Clone internal structure
47 $foreign->{volume} = $self->{volume};
48 my ($u, $fu) = ($self->_spec->updir, $foreign->_spec->updir);
49 $foreign->{dirs} = [ map {$_ eq $u ? $fu : $_} @{$self->{dirs}}];
56 return $s->catpath($self->{volume},
57 $s->catdir(@{$self->{dirs}}),
61 sub volume { shift()->{volume} }
64 local $Path::Class::Foreign = $_[0]->{file_spec_class} if $_[0]->{file_spec_class};
65 return Path::Class::File->new(@_);
70 my $d = $self->{dirs};
74 if ($offset < 0) { $offset = $#$d + $offset + 1 }
76 return wantarray ? @$d[$offset .. $#$d] : $d->[$offset] unless @_;
79 if ($length < 0) { $length = $#$d + $length + 1 - $offset }
80 return @$d[$offset .. $length + $offset - 1];
85 return $self->new($self, @_);
90 my $dirs = $self->{dirs};
91 my ($curdir, $updir) = ($self->_spec->curdir, $self->_spec->updir);
93 if ($self->is_absolute) {
94 my $parent = $self->new($self);
95 pop @{$parent->{dirs}};
98 } elsif ($self eq $curdir) {
99 return $self->new($updir);
101 } elsif (!grep {$_ ne $updir} @$dirs) { # All updirs
102 return $self->new($self, $updir); # Add one more
104 } elsif (@$dirs == 1) {
105 return $self->new($curdir);
108 my $parent = $self->new($self);
109 pop @{$parent->{dirs}};
115 # File::Spec->abs2rel before version 3.13 returned the empty string
116 # when the two paths were equal - work around it here.
118 my $rel = $self->_spec->abs2rel($self->stringify, @_);
119 return $self->new( length $rel ? $rel : $self->_spec->curdir );
122 sub open { IO::Dir->new(@_) }
123 sub mkpath { File::Path::mkpath(shift()->stringify, @_) }
124 sub rmtree { File::Path::rmtree(shift()->stringify, @_) }
132 my %opts = (preorder => 1, depthfirst => 0, @_);
134 my $callback = $opts{callback}
135 or Carp::croak( "Must provide a 'callback' parameter to recurse()" );
141 $opts{depthfirst} && $opts{preorder}
145 unshift @queue, $dir->children;
151 push @queue, $dir->children;
155 $visit_entry->($_) foreach $dir->children;
161 if ($entry->is_dir) { $visit_dir->($entry) } # Will call $callback
162 else { $callback->($entry) }
166 $visit_entry->( shift @queue );
171 my ($self, %opts) = @_;
173 my $dh = $self->open or Carp::croak( "Can't open directory $self: $!" );
176 while (my $entry = $dh->read) {
177 # XXX What's the right cross-platform way to do this?
178 next if (!$opts{all} && ($entry eq '.' || $entry eq '..'));
179 push @out, $self->file($entry);
180 $out[-1] = $self->subdir($entry) if -d $out[-1];
187 unless ($self->{dh}) {
188 $self->{dh} = $self->open or Carp::croak( "Can't open directory $self: $!" );
191 my $next = $self->{dh}->read;
192 unless (defined $next) {
197 # Figure out whether it's a file or directory
198 my $file = $self->file($next);
199 $file = $self->subdir($next) if -d $file;
204 my ($self, $other) = @_;
205 die "No second entity given to subsumes()" unless $other;
207 $other = $self->new($other) unless UNIVERSAL::isa($other, __PACKAGE__);
208 $other = $other->dir unless $other->is_dir;
210 if ($self->is_absolute) {
211 $other = $other->absolute;
212 } elsif ($other->is_absolute) {
213 $self = $self->absolute;
216 $self = $self->cleanup;
217 $other = $other->cleanup;
220 return 0 unless $other->volume eq $self->volume;
223 # The root dir subsumes everything (but ignore the volume because
224 # we've already checked that)
225 return 1 if "@{$self->{dirs}}" eq "@{$self->new('')->{dirs}}";
228 while ($i <= $#{ $self->{dirs} }) {
229 return 0 if $i > $#{ $other->{dirs} };
230 return 0 if $self->{dirs}[$i] ne $other->{dirs}[$i];
237 my ($self, $other) = @_;
238 return !!(-d $self and (-e $other or -l $other) and $self->subsumes($other));
246 Path::Class::Dir - Objects representing directories
250 use Path::Class qw(dir); # Export a short constructor
252 my $dir = dir('foo', 'bar'); # Path::Class::Dir object
253 my $dir = Path::Class::Dir->new('foo', 'bar'); # Same thing
255 # Stringifies to 'foo/bar' on Unix, 'foo\bar' on Windows, etc.
258 if ($dir->is_absolute) { ... }
259 if ($dir->is_relative) { ... }
261 my $v = $dir->volume; # Could be 'C:' on Windows, empty string
262 # on Unix, 'Macintosh HD:' on Mac OS
264 $dir->cleanup; # Perform logical cleanup of pathname
265 $dir->resolve; # Perform physical cleanup of pathname
267 my $file = $dir->file('file.txt'); # A file in this directory
268 my $subdir = $dir->subdir('george'); # A subdirectory
269 my $parent = $dir->parent; # The parent directory, 'foo'
271 my $abs = $dir->absolute; # Transform to absolute path
272 my $rel = $abs->relative; # Transform to relative path
273 my $rel = $abs->relative('/foo'); # Relative to /foo
275 print $dir->as_foreign('Mac'); # :foo:bar:
276 print $dir->as_foreign('Win32'); # foo\bar
278 # Iterate with IO::Dir methods:
279 my $handle = $dir->open;
280 while (my $file = $handle->read) {
281 $file = $dir->file($file); # Turn into Path::Class::File object
285 # Iterate with Path::Class methods:
286 while (my $file = $dir->next) {
287 # $file is a Path::Class::File or Path::Class::Dir object
294 The C<Path::Class::Dir> class contains functionality for manipulating
295 directory names in a cross-platform way.
301 =item $dir = Path::Class::Dir->new( <dir1>, <dir2>, ... )
303 =item $dir = dir( <dir1>, <dir2>, ... )
305 Creates a new C<Path::Class::Dir> object and returns it. The
306 arguments specify names of directories which will be joined to create
307 a single directory object. A volume may also be specified as the
308 first argument, or as part of the first argument. You can use
309 platform-neutral syntax:
311 my $dir = dir( 'foo', 'bar', 'baz' );
313 or platform-native syntax:
315 my $dir = dir( 'foo/bar/baz' );
317 or a mixture of the two:
319 my $dir = dir( 'foo/bar', 'baz' );
321 All three of the above examples create relative paths. To create an
322 absolute path, either use the platform native syntax for doing so:
324 my $dir = dir( '/var/tmp' );
326 or use an empty string as the first argument:
328 my $dir = dir( '', 'var', 'tmp' );
330 If the second form seems awkward, that's somewhat intentional - paths
331 like C</var/tmp> or C<\Windows> aren't cross-platform concepts in the
332 first place (many non-Unix platforms don't have a notion of a "root
333 directory"), so they probably shouldn't appear in your code if you're
334 trying to be cross-platform. The first form is perfectly natural,
335 because paths like this may come from config files, user input, or
338 As a special case, since it doesn't otherwise mean anything useful and
339 it's convenient to define this way, C<< Path::Class::Dir->new() >> (or
340 C<dir()>) refers to the current directory (C<< File::Spec->curdir >>).
341 To get the current directory as an absolute path, do C<<
344 Finally, as another special case C<dir(undef)> will return undef,
345 since that's usually an accident on the part of the caller, and
346 returning the root directory would be a nasty surprise just asking for
347 trouble a few lines later.
349 =item $dir->stringify
351 This method is called internally when a C<Path::Class::Dir> object is
352 used in a string context, so the following are equivalent:
354 $string = $dir->stringify;
359 Returns the volume (e.g. C<C:> on Windows, C<Macintosh HD:> on Mac OS,
360 etc.) of the directory object, if any. Otherwise, returns the empty
365 Returns a boolean value indicating whether this object represents a
366 directory. Not surprisingly, C<Path::Class::File> objects always
367 return false, and C<Path::Class::Dir> objects always return true.
369 =item $dir->is_absolute
371 Returns true or false depending on whether the directory refers to an
372 absolute path specifier (like C</usr/local> or C<\Windows>).
374 =item $dir->is_relative
376 Returns true or false depending on whether the directory refers to a
377 relative path specifier (like C<lib/foo> or C<./dir>).
381 Performs a logical cleanup of the file path. For instance:
383 my $dir = dir('/foo//baz/./foo')->cleanup;
384 # $dir now represents '/foo/baz/foo';
388 Performs a physical cleanup of the file path. For instance:
390 my $dir = dir('/foo//baz/../foo')->resolve;
391 # $dir now represents '/foo/foo', assuming no symlinks
393 This actually consults the filesystem to verify the validity of the
396 =item $file = $dir->file( <dir1>, <dir2>, ..., <file> )
398 Returns a C<Path::Class::File> object representing an entry in C<$dir>
399 or one of its subdirectories. Internally, this just calls C<<
400 Path::Class::File->new( @_ ) >>.
402 =item $subdir = $dir->subdir( <dir1>, <dir2>, ... )
404 Returns a new C<Path::Class::Dir> object representing a subdirectory
407 =item $parent = $dir->parent
409 Returns the parent directory of C<$dir>. Note that this is the
410 I<logical> parent, not necessarily the physical parent. It really
411 means we just chop off entries from the end of the directory list
412 until we cain't chop no more. If the directory is relative, we start
413 using the relative forms of parent directories.
415 The following code demonstrates the behavior on absolute and relative
418 $dir = dir('/foo/bar');
420 print "Absolute: $dir\n";
424 $dir = dir('foo/bar');
426 print "Relative: $dir\n";
430 ########### Output on Unix ################
444 =item @list = $dir->children
446 Returns a list of C<Path::Class::File> and/or C<Path::Class::Dir>
447 objects listed in this directory, or in scalar context the number of
448 such objects. Obviously, it is necessary for C<$dir> to
449 exist and be readable in order to find its children.
451 Note that the children are returned as subdirectories of C<$dir>,
452 i.e. the children of F<foo> will be F<foo/bar> and F<foo/baz>, not
455 Ordinarily C<children()> will not include the I<self> and I<parent>
456 entries C<.> and C<..> (or their equivalents on non-Unix systems),
457 because that's like I'm-my-own-grandpa business. If you do want all
458 directory entries including these special ones, pass a true value for
459 the C<all> parameter:
461 @c = $dir->children(); # Just the children
462 @c = $dir->children(all => 1); # All entries
464 =item $abs = $dir->absolute
466 Returns a C<Path::Class::Dir> object representing C<$dir> as an
467 absolute path. An optional argument, given as either a string or a
468 C<Path::Class::Dir> object, specifies the directory to use as the base
469 of relativity - otherwise the current working directory will be used.
471 =item $rel = $dir->relative
473 Returns a C<Path::Class::Dir> object representing C<$dir> as a
474 relative path. An optional argument, given as either a string or a
475 C<Path::Class::Dir> object, specifies the directory to use as the base
476 of relativity - otherwise the current working directory will be used.
478 =item $boolean = $dir->subsumes($other)
480 Returns true if this directory spec subsumes the other spec, and false
481 otherwise. Think of "subsumes" as "contains", but we only look at the
482 I<specs>, not whether C<$dir> actually contains C<$other> on the
485 The C<$other> argument may be a C<Path::Class::Dir> object, a
486 C<Path::Class::File> object, or a string. In the latter case, we
487 assume it's a directory.
490 dir('foo/bar' )->subsumes(dir('foo/bar/baz')) # True
491 dir('/foo/bar')->subsumes(dir('/foo/bar/baz')) # True
492 dir('foo/bar' )->subsumes(dir('bar/baz')) # False
493 dir('/foo/bar')->subsumes(dir('foo/bar')) # False
496 =item $boolean = $dir->contains($other)
498 Returns true if this directory actually contains C<$other> on the
499 filesystem. C<$other> doesn't have to be a direct child of C<$dir>,
500 it just has to be subsumed.
502 =item $foreign = $dir->as_foreign($type)
504 Returns a C<Path::Class::Dir> object representing C<$dir> as it would
505 be specified on a system of type C<$type>. Known types include
506 C<Unix>, C<Win32>, C<Mac>, C<VMS>, and C<OS2>, i.e. anything for which
507 there is a subclass of C<File::Spec>.
509 Any generated objects (subdirectories, files, parents, etc.) will also
512 =item $foreign = Path::Class::Dir->new_foreign($type, @args)
514 Returns a C<Path::Class::Dir> object representing C<$dir> as it would
515 be specified on a system of type C<$type>. Known types include
516 C<Unix>, C<Win32>, C<Mac>, C<VMS>, and C<OS2>, i.e. anything for which
517 there is a subclass of C<File::Spec>.
519 The arguments in C<@args> are the same as they would be specified in
522 =item @list = $dir->dir_list([OFFSET, [LENGTH]])
524 Returns the list of strings internally representing this directory
525 structure. Each successive member of the list is understood to be an
526 entry in its predecessor's directory list. By contract, C<<
527 Path::Class->new( $dir->dir_list ) >> should be equivalent to C<$dir>.
529 The semantics of this method are similar to Perl's C<splice> or
530 C<substr> functions; they return C<LENGTH> elements starting at
531 C<OFFSET>. If C<LENGTH> is omitted, returns all the elements starting
532 at C<OFFSET> up to the end of the list. If C<LENGTH> is negative,
533 returns the elements from C<OFFSET> onward except for C<-LENGTH>
534 elements at the end. If C<OFFSET> is negative, it counts backward
535 C<OFFSET> elements from the end of the list. If C<OFFSET> and
536 C<LENGTH> are both omitted, the entire list is returned.
538 In a scalar context, C<dir_list()> with no arguments returns the
539 number of entries in the directory list; C<dir_list(OFFSET)> returns
540 the single element at that offset; C<dir_list(OFFSET, LENGTH)> returns
541 the final element that would have been returned in a list context.
543 =item $fh = $dir->open()
545 Passes C<$dir> to C<< IO::Dir->open >> and returns the result as an
546 C<IO::Dir> object. If the opening fails, C<undef> is returned and
549 =item $dir->mkpath($verbose, $mode)
551 Passes all arguments, including C<$dir>, to C<< File::Path::mkpath()
552 >> and returns the result (a list of all directories created).
554 =item $dir->rmtree($verbose, $cautious)
556 Passes all arguments, including C<$dir>, to C<< File::Path::rmtree()
557 >> and returns the result (the number of files successfully deleted).
561 Removes the directory, which must be empty. Returns a boolean value
562 indicating whether or not the directory was successfully removed.
563 This method is mainly provided for consistency with
564 C<Path::Class::File>'s C<remove()> method.
566 =item $dir_or_file = $dir->next()
568 A convenient way to iterate through directory contents. The first
569 time C<next()> is called, it will C<open()> the directory and read the
570 first item from it, returning the result as a C<Path::Class::Dir> or
571 C<Path::Class::File> object (depending, of course, on its actual
572 type). Each subsequent call to C<next()> will simply iterate over the
573 directory's contents, until there are no more items in the directory,
574 and then the undefined value is returned. For example, to iterate
575 over all the regular files in a directory:
577 while (my $file = $dir->next) {
578 next unless -f $file;
579 my $fh = $file->open('r') or die "Can't read $file: $!";
583 If an error occurs when opening the directory (for instance, it
584 doesn't exist or isn't readable), C<next()> will throw an exception
585 with the value of C<$!>.
587 =item $dir->recurse( callback => sub {...} )
589 Iterates through this directory and all of its children, and all of
590 its children's children, etc., calling the C<callback> subroutine for
591 each entry. This is a lot like what the C<File::Find> module does,
592 and of course C<File::Find> will work fine on C<Path::Class> objects,
593 but the advantage of the C<recurse()> method is that it will also feed
594 your callback routine C<Path::Class> objects rather than just pathname
597 The C<recurse()> method requires a C<callback> parameter specifying
598 the subroutine to invoke for each entry. It will be passed the
599 C<Path::Class> object as its first argument.
601 C<recurse()> also accepts two boolean parameters, C<depthfirst> and
602 C<preorder> that control the order of recursion. The default is a
603 preorder, breadth-first search, i.e. C<< depthfirst => 0, preorder => 1 >>.
604 At the time of this writing, all combinations of these two parameters
605 are supported I<except> C<< depthfirst => 0, preorder => 0 >>.
607 =item $st = $file->stat()
609 Invokes C<< File::stat::stat() >> on this directory and returns a
610 C<File::stat> object representing the result.
612 =item $st = $file->lstat()
614 Same as C<stat()>, but if C<$file> is a symbolic link, C<lstat()>
615 stats the link instead of the directory the link points to.
621 Ken Williams, ken@mathforum.org
625 Path::Class, Path::Class::File, File::Spec