sub dir_ensure {
for (@_) { # handles multiple DIRs
my $path = ($_ // die("Dir must be specified")) =~ s!/$!!sr;
next if -d $path; # DIR is already there
die("Path '$path' already exists and it's not a DIR") if -e _;
my $parent = $path =~ m"^(/[^/].*?)/(?!\.{1,2}$)[^/]+$"s
? $1 : die("Invalid path '$path'");
dir_ensure($parent); # ensure parent DIR exists
mkdir($path) or die("Failed to create DIR $path $!");
}
}
Problems with that code:
- Recursion is not needed to split a path into a series of directories, as explained in other posts in this thread.
- The code assumes a single root directory. There are several operating systems that have more than one root directory. (DOS, Windows, OS/2, ...)
- There is a race condition: You stat() a part of the path way before you mkdir that part (see TOCTTOU). To avoid that problem, just call mkdir() and check its result. Expect EEXISTS for already existing directories.
- There is at least one module that already takes care of all those issues, plus OS-specific surprises: File::Path
Alexander
--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)