Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages


home | help
Vimana::Recursive(3)  User Contributed Perl Documentation Vimana::Recursive(3)

       Vimana::Recursive - Perl	extension for recursively copying files	and

	 use Vimana::Recursive qw(fcopy	rcopy dircopy fmove rmove dirmove);

	 fcopy($orig,$new[,$buf]) or die $!;
	 rcopy($orig,$new[,$buf]) or die $!;
	 dircopy($orig,$new[,$buf]) or die $!;

	 fmove($orig,$new[,$buf]) or die $!;
	 rmove($orig,$new[,$buf]) or die $!;
	 dirmove($orig,$new[,$buf]) or die $!;

	 rcopy_glob("orig/stuff-*", $trg [, $buf]) or die $!;
	 rmove_glob("orig/stuff-*", $trg [,$buf]) or die $!;

       This module copies and moves directories	recursively (or	single files,
       well... singley)	to an optional depth and attempts to preserve each
       file or directory's mode.

       None by default.	But you	can export all the functions as	in the example
       above and the path* functions if	you wish.

       This function uses File::Copy's copy() function to copy a file but not
       a directory. Any	directories are	recursively created if need be.	 One
       difference to File::Copy::copy()	is that	fcopy attempts to preserve the
       mode (see Preserving Mode below)	The optional $buf in the synopsis if
       the same	as File::Copy::copy()'s	3rd argument returns the same as
       File::Copy::copy() in scalar context and	1,0,0 in list context to
       accomidate rcopy()'s list context on regular files. (See	below for more

       This function recursively traverses the $orig directory's structure and
       recursively copies it to	the $new directory.  $new is created if
       necessary (multiple non existant	directories is ok (IE foo/bar/baz).
       The script logically and	portably creates all of	them if	necessary).
       It attempts to preserve the mode	(see Preserving	Mode below) and	by
       default it copies all the way down into the directory, (see Managing
       Depth) below.  If a directory is	not specified it croaks	just like
       fcopy croaks if its not a file that is specified.

       returns true or false, for true in scalar context it returns the	number
       of files	and directories	copied,	In list	context	it returns the number
       of files	and directories, number	of directories only, depth level

	 my $num_of_files_and_dirs = dircopy($orig,$new);
	 my($num_of_files_and_dirs,$num_of_dirs,$depth_traversed) = dircopy($orig,$new);

       Normally	it stops and return's if a copy	fails, to continue on
       regardless set $Vimana::Recursive::SkipFlop to true.

	   local $Vimana::Recursive::SkipFlop =	1;

       That way	it will	copy everythgingit can ina directory and won't stop
       because of permissions, etc...

       This function will allow	you to specify a file *or* directory. It calls
       fcopy() if its a	file and dircopy() if its a directory.	If you call
       rcopy() (or fcopy() for that matter) on a file in list context, the
       values will be 1,0,0 since no directories and no	depth are used.	 This
       is important becasue if its a directory in list context and there is
       only the	initial	directory the return value is 1,1,1.

       This function lets you specify a	pattern	suitable for perl's glob() as
       the first argument. Subsequently	each path returned by perl's glob()
       gets rcopy()ied.

       It returns and array whose items	are array refs that contain the	return
       value of	each rcopy() call.

       It forces behavior as if	$Vimana::Recursive::CPRFComp is	true.

       Copies the file then removes the	original. You can manage the path the
       original	file is	in according to	$RemvBase.

       Uses dircopy() to copy the directory then removes the original. You can
       manage the path the original directory is in according to $RemvBase.

       Like rcopy() but	calls fmove() or dirmove() instead.

       Like rcopy_glob() but calls rmove() instead of rcopy()


       Default is false. When set to true the *move() functions	will not only
       attempt to remove the original file or directory	but will remove	the
       given path it is	in.

       So if you:

	  rmove('foo/bar/baz', '/etc/');
	  # "baz" is removed from foo/bar after	it is successfully copied to /etc/

	  local	$Vimana::Recursive::Remvbase = 1;
	  # if baz is successfully copied to /etc/ :
	  # first "baz"	is removed from	foo/bar
	  # then "foo/bar is removed via pathrm()


       Default is false. When set to true it calls pathempty() before any
       directories are removed to empty	the directory so it can	be rmdir()'ed
       when $RemvBase is in effect.

   Creating and	Removing Paths

       Default is false. If set	to true	 rmdir(), mkdir(), and pathempty()
       calls in	pathrm() and pathmk() do not return() on failure.

       If its set to true they just silently go	about their business
       regardless. This	isn't a	good idea but its there	if you want it.


       Mode to pass to any mkdir() calls. Defaults to 0777 as per umask()'s
       POD. Explicitly having this allows older	perls to be able to use	FCR
       and might add a bit of flexibility for you.

       Any value you set it to should be suitable for oct()

       Path functions

       These functions exist soley because they	were necessary for the move
       and copy	functions to have the features they do and not because they
       are of themselves the purpose of	this module. That being	said, here is
       how they	work so	you can	understand how the copy	and move funtions work
       and use them by themselves if you wish.


       Removes a given path recursively. It removes the	*entire* path so be

       Returns 2 if the	given path is not a directory.

	 Vimana::Recursive::pathrm('foo/bar/baz') or die $!;
	 # foo no longer exists

       Same as:

	 rmdir 'foo/bar/baz' or	die $!;
	 rmdir 'foo/bar' or die	$!;
	 rmdir 'foo' or	die $!;

       An optional second argument makes it call pathempty() before any
       rmdir()'s when set to true.

	 Vimana::Recursive::pathrm('foo/bar/baz', 1) or	die $!;
	 # foo no longer exists

       Same as:PFSCheck

	 Vimana::Recursive::pathempty('foo/bar/baz') or	die $!;
	 rmdir 'foo/bar/baz' or	die $!;
	 Vimana::Recursive::pathempty('foo/bar/') or die $!;
	 rmdir 'foo/bar' or die	$!;
	 Vimana::Recursive::pathempty('foo/') or die $!;
	 rmdir 'foo' or	die $!;

       An optional third argument acts like $Vimana::Recursive::NoFtlPth,
       again probably not a good idea.


       Recursively removes the given directory's contents so it	is empty.
       returns 2 if argument is	not a directory, 1 on successfully emptying
       the directory.

	  Vimana::Recursive::pathempty($pth) or	die $!;
	  # $pth is now	an empty directory


       Creates a given path recursively. Creates foo/bar/baz even if foo does
       not exist.

	  Vimana::Recursive::pathmk('foo/bar/baz') or die $!;

       An optional second argument if true acts	just like
       $Vimana::Recursive::NoFtlPth, which means you'd never get your die() if
       something went wrong. Again, probably a *bad* idea.


       Same as rmdir() but it calls pathempty()	first to recursively empty it
       first since rmdir can not remove	a directory with contents.  Just
       removes the top directory the path given	instead	of the entire path
       like pathrm(). Return 2 if given	argument does not exist	(IE its
       already gone). Return false if it exists	but is not a directory.

   Preserving Mode
       By default a quiet attempt is made to change the	new file or directory
       to the mode of the old one.  To turn this behavior off set
	 $Vimana::Recursive::KeepMode to false;

   Managing Depth
       You can set the maximum depth a directory structure is recursed by
	 $Vimana::Recursive::MaxDepth to a whole number	greater	than 0.

       If your system supports symlinks	then symlinks will be copied as
       symlinks	instead	of as the target file.	Perl's symlink() is used
       instead of File::Copy's copy() You can customize	this behavior by
       setting $Vimana::Recursive::CopyLink to a true or false value.  It is
       already set to true or false dending on your system's support of
       symlinks	so you can check it with an if statement to see	how it will

	   if($Vimana::Recursive::CopyLink) {
	       print "Symlinks will be preserved\n";
	   } else {
	       print "Symlinks will not	be preserved because your system does not support it\n";

       If symlinks are being copied you	can set	$Vimana::Recursive::BdTrgWrn
       to true to make it carp when it copies a	link whose target does not
       exist. Its false	by default.

	   local $Vimana::Recursive::BdTrgWrn  = 1;

   Removing existing target file or directory before copying.
       This can	be done	by setting $Vimana::Recursive::RMTrgFil	or
       $Vimana::Recursive::RMTrgDir for	file or	directory behavior

       0 = off (This is	the default)

       1 = carp() $! if	removal	fails

       2 = return if removal fails

	   local $Vimana::Recursive::RMTrgFil =	1;
	   fcopy($orig,	$target) or die	$!;
	   # if	it fails it does warn()	and keeps going

	   local $Vimana::Recursive::RMTrgDir =	2;
	   dircopy($orig, $target) or die $!;
	   # if	it fails it does your "or die"

       This should be unnecessary most of the time but its there if you	need
       it :)

   Turning off stat() check
       By default the files or directories are checked to see if they are the
       same (IE	linked,	or two paths (absolute/relative	or different relative
       paths) to the same file)	by comparing the file's	stat() info.  It's a
       very efficient check that croaks	if they	are and	shouldn't be turned
       off but if you must for some weird reason just set
       $Vimana::Recursive::PFSCheck to a false value. ("PFS" stands for
       "Physical File System")

   Emulating cp	-rf dir1/ dir2/
       By default dircopy($dir1,$dir2) will put	$dir1's	contents right into
       $dir2 whether $dir2 exists or not.

       You can make dircopy() emulate cp -rf by	setting
       $Vimana::Recursive::CPRFComp to true.

       NOTE: This only emulates	-f in the sense	that it	does not prompt. It
       does not	remove the target file or directory if it exists.  If you need
       to do that then use the variables $RMTrgFil and $RMTrgDir described in
       "Removing existing target file or directory before copying" above.

       That means that if $dir2	exists it puts the contents into $dir2/$dir1
       instead of $dir2	just like cp -rf.  If $dir2 does not exist then	the
       contents	go into	$dir2 like normal (also	like cp	-rf)

       So assuming 'foo/file':

	   dircopy('foo', 'bar') or die	$!;
	   # if	bar does not exist the result is bar/file
	   # if	bar does exist the result is bar/file

	   $Vimana::Recursive::CPRFComp	= 1;
	   dircopy('foo', 'bar') or die	$!;
	   # if	bar does not exist the result is bar/file
	   # if	bar does exist the result is bar/foo/file

       You can also specify a star for cp -rf glob type	behavior:

	   dircopy('foo/*', 'bar') or die $!;
	   # if	bar does not exist the result is bar/file
	   # if	bar does exist the result is bar/file

	   $Vimana::Recursive::CPRFComp	= 1;
	   dircopy('foo/*', 'bar') or die $!;
	   # if	bar does not exist the result is bar/file
	   # if	bar does exist the result is bar/file

       NOTE: The '*' is	only like cp -rf foo/* and *DOES NOT EXPAND PARTIAL
       DIRECTORY NAMES LIKE YOUR SHELL DOES* (IE not like cp -rf fo* to	copy

   Allowing Copy Loops
       If you want to allow:

	 cp -rf	. foo/

       type behavior set $Vimana::Recursive::CopyLoop to true.

       This is false by	default	so that	a check	is done	to see if the source
       directory will contain the target directory and croaks to avoid this

       If you ever find	a situation where $CopyLoop = 1	is desirable let me
       know (IE	its a bad bad idea but is there	if you want it)

       (Note: On Windows this was necessary since it uses stat() to detemine
       samedness and stat() is essencially useless for this on Windows.	 The
       test is now simply skipped on Windows but I'd rather have an actual
       reliable	check if anyone	in Microsoft land would	care to	share)

       File::Copy File::Spec

       I am currently working on and reviewing some other modules to use in
       the new interface so we can lose	the horrid globals as well as some
       other undesirable traits	and also more easily make available some long
       standing	requests.

       Tests will be easier to do with the new interface and hence the testing
       focus will shift	to the new interface and aim to	be comprehensive.

       The old interface will work, it just won't be brought in	until it is
       used, so	it will	add no overhead	for users of the new interface.

       I'll add	this after the latest verision has been	out for	a while	with
       no new features or issues found :)

       Daniel Muey, <>

       Copyright 2004 by Daniel	Muey

       This library is free software; you can redistribute it and/or modify it
       under the same terms as Perl itself.

perl v5.32.0			  2010-03-17		  Vimana::Recursive(3)


Want to link to this manual page? Use this URL:

home | help