Make directory path

From Rosetta Code
Revision as of 19:00, 18 August 2016 by rosettacode>PKai (Added F# version)
Task
Make directory path
You are encouraged to solve this task according to the task description, using any language you may know.

Create a directory and any missing parents.

This task is named after the posix mkdir -p command, and several libraries which implement the same behavior.

Please implement a function of a single path string (for example ./path/to/dir) which has the above side-effect. If the directory already exists, return successfully. Ideally implementations will work equally well cross-platform (on windows, linux, and OS X).

It's likely that your language implements such a function as part of its standard library. If so, please also show how such a function would be implemented.

AWK

<lang AWK>

  1. syntax: GAWK -f MAKE_DIRECTORY_PATH.AWK path ...

BEGIN {

   for (i=1; i<=ARGC-1; i++) {
     path = ARGV[i]
     msg = (make_dir_path(path) == 0) ? "created" : "exists"
     printf("'%s' %s\n",path,msg)
   }
   exit(0)

} function make_dir_path(path, cmd) {

  1. cmd = sprintf("mkdir -p '%s'",path) # Unix
   cmd = sprintf("MKDIR \"%s\" 2>NUL",path) # MS-Windows
   return system(cmd)

} </lang>

sample command and output under Windows 8:

GAWK -f MAKE_DIRECTORY_PATH.AWK \TEMP\A \TEMP\A "\TEMP\A\B C"

'\TEMP\A' created
'\TEMP\A' exists
'\TEMP\A\B C' created

C

<lang c>#include <stdio.h>

  1. include <stdlib.h>
  2. include <libgen.h>
  3. include <string.h>
  4. include <sys/stat.h>
  5. include <sys/types.h>

int main (int argc, char **argv) {

   char *str, *s;
   struct stat statBuf;
   if (argc != 2) {
       fprintf (stderr, "usage: %s <path>\n", basename (argv[0]));
       exit (1);
   }
   s = argv[1];
   while ((str = strtok (s, "/")) != NULL) {
       if (str != s) {
           str[-1] = '/';
       }
       if (stat (argv[1], &statBuf) == -1) {
           mkdir (argv[1], 0);
       } else {
           if (! S_ISDIR (statBuf.st_mode)) {
               fprintf (stderr, "couldn't create directory %s\n", argv[1]);
               exit (1);
           }
       }
       s = NULL;
   }
   return 0;

}</lang>

Common Lisp

<lang lisp> (ensure-directories-exist "your/path/name") </lang>

Clojure

<lang clojure>(defn mkdirp [path]

 (let [dir (java.io.File. path)]
   (if (.exists dir)
     true
     (.mkdirs dir))))</lang>

Elixir

Tries to create the directory `path`. Missing parent directories are created. <lang elixir>File.mkdir_p("./path/to/dir")</lang>

ERRE

ERRE has the procedure "OS_MKDIR" in PC.LIB standard library, that creates a directory with all missing parents. Existing directory are simply ignored. <lang ERRE>OS_MKDIR("C:\EXAMPLES\03192015")</lang>

F#

The library function System.IO.Directory.CreateDirectory also returns a DirectoryInfo object of the deepest directory in the path.

In the F# REPL:

Output:
> System.IO.Directory.CreateDirectory (System.IO.Directory.GetCurrentDirectory())
;;
val it : System.IO.DirectoryInfo =
  Temp {Attributes = Directory;
        CreationTime = 2016-06-01 04:12:25;
        CreationTimeUtc = 2016-06-01 02:12:25;
        Exists = true;
        Extension = "";
        FullName = "C:\Users\Kai\AppData\Local\Temp";
        LastAccessTime = 2016-08-18 20:42:21;
        LastAccessTimeUtc = 2016-08-18 18:42:21;
        LastWriteTime = 2016-08-18 20:42:21;
        LastWriteTimeUtc = 2016-08-18 18:42:21;
        Name = "Temp";
        Parent = Local;
        Root = C:\;}
> 

Go

The standard packages include os.MkdirAll which does exactly this (and its source is also available via that link). <lang go> os.MkdirAll("/tmp/some/path/to/dir", 0770)</lang>

Haskell

<lang Haskell> import System.Directory (createDirectory, setCurrentDirectory) import Data.List.Split (splitOn)

main :: IO () main = do

 let path = splitOn "/" "path/to/dir"
 mapM_ (\x -> createDirectory x >> setCurrentDirectory x) path

</lang>

J

The verb pathcreate in the addon package general/dirutils will create any non-existing directories in a path. It works on Windows, Linux and OS X.

<lang J>require 'general/dirutils' pathcreate '/tmp/some/path/to/dir'</lang>

Code is similar to the following: <lang J>pathcreate=: monad define

 todir=. termsep_j_ jpathsep y
 todirs=. }. ,each /\ <;.2 todir  NB. base dirs
 msk=. -.direxist todirs          NB. 1 for each non-existing dir
 msk=. 0 (i. msk i: 0)}msk
 dircreate msk#todirs             NB. create non-existing base dirs

)

dircreate=: monad define

 y=. boxxopen y
 msk=. -.direxist y
 if. -:$msk do. msk=. (#y)#msk end.
 res=. 1!:5 msk#y
 msk #inv ,res

)

direxist=: 2 = ftype&>@:boxopen</lang>

Java

The Java method for this is mkdirs and can be found in java.io.File. The source is in the src.zip of the JDK root directory. <lang java>import java.io.File;

public interface Test {

   public static void main(String[] args) {
       try {
           File f = new File("C:/parent/test");
           if (f.mkdirs())
               System.out.println("path successfully created");
       } catch (Exception e) {
           e.printStackTrace();
       }
   }

}</lang>

JavaScript

Works with: Node.js

Simplified version of the popular mkdirp library:

<lang Javascript>var path = require('path'); var fs = require('fs');

function mkdirp (p, cb) {

   cb = cb || function () {};
   p = path.resolve(p);
   fs.mkdir(p, function (er) {
       if (!er) {
           return cb(null);
       }
       switch (er.code) {
           case 'ENOENT':
               // The directory doesn't exist. Make its parent and try again.
               mkdirp(path.dirname(p), function (er) {
                   if (er) cb(er);
                   else mkdirp(p, cb);
               });
               break;
               // In the case of any other error, something is borked.
           default:
               cb(er);
               break;
       }
   });

}</lang>

Mathematica

Creates directory specified by path, creating intermediate directories as necessary, and never fails if path already exists. <lang Mathematica>mkdirp[path_] := Quiet[CreateDirectory[path,{CreateIntermediateDirectories->True}],{CreateDirectory::filex}]</lang>

Perl

Using the File::Path core module:

<lang perl>use File::Path qw(make_path);

make_path('path/to/dir')</lang>

Perl 6

Works with: rakudo version 2016.06

There is a built-in function for this:

<lang perl6>mkdir 'path/to/dir'</lang>

PowerShell

<lang PowerShell> New-Item -Path ".\path\to\dir" -ItemType Directory -ErrorAction SilentlyContinue </lang>

Python

<lang Python> from errno import EEXIST from os import mkdir, curdir from os.path import split, exists

def mkdirp(path, mode=0777):

   head, tail = split(path)
   if not tail:
       head, tail = split(head)
   if head and tail and not exists(head):
       try:
           mkdirp(head, mode)
       except OSError as e:
           # be happy if someone already created the path
           if e.errno != EEXIST:
               raise
       if tail == curdir:  # xxx/newdir/. exists if xxx/newdir exists
           return
   try:
       mkdir(path, mode)
   except OSError as e:
       # be happy if someone already created the path
       if e.errno != EEXIST:
           raise

</lang>

Above is a modified version of the standard library's os.makedirs, for pedagogical purposes. In practice, you would be more likely to use the standard library call:

<lang Python> def mkdirp(path):

   try:
       os.makedirs(path)
   except OSError as exc: # Python >2.5
       if exc.errno == errno.EEXIST and os.path.isdir(path):
           pass
       else: raise

</lang>

In Python3 this becomes even simpler:

<lang Python> def mkdirp(path):

   os.makedirs(path, exist_ok=True)

</lang>

Racket

Uses make-directory* (NB the star — that causes the intermediate directories to be produced).

Canonical documentation at Racket Documentation for Filesystem

Creates directory specified by path, creating intermediate

directories as necessary, and never failing if path exists already.

<lang racket>#lang racket (define path-str "/tmp/woo/yay") (define path/..-str "/tmp/woo")

clean up from a previous run

(when (directory-exists? path-str)

 (delete-directory path-str)
 (delete-directory path/..-str))
delete-directory/files could also be used -- but that requires goggles and rubber
gloves to handle safely!

(define (report-path-exists)

 (printf "~s exists (as a directory?):~a~%~s exists (as a directory?):~a~%~%"
         path/..-str (directory-exists? path/..-str)
         path-str (directory-exists? path-str)))

(report-path-exists)

Really ... this is the only bit that matters!

(make-directory* path-str)

(report-path-exists)</lang>

Output:
"/tmp/woo" exists (as a directory?):#f
"/tmp/woo/yay" exists (as a directory?):#f

"/tmp/woo" exists (as a directory?):#t
"/tmp/woo/yay" exists (as a directory?):#t

REXX

The following works with any modern (Microsoft) Windows ® and/or DOS.

Operating system note:   all versions of Microsoft ® DOS require the use of a blackslash   [\]   instead of a forward slash   [/].

Usage note:   without the error messages being suppressed, the   MKDIR   command will issue an error message if the subdirectory (or its path) already exists. <lang rexx>/*REXX program creates a directory (folder) and all its parent paths as necessary. */ trace off /*suppress possible warning msgs.*/

dPath = 'path\to\dir' /*define directory (folder) path.*/

'MKDIR' dPath "2>nul" /*alias could be used: MD dPath */

                                                      /*stick a fork in it, we're done.*/</lang>

Ring

<lang ring> System("mkdir C:\Ring\docs") isdir("C:\Ring\docs")

see isdir("C:\Ring\docs") + nl func isdir cDir

    try
       dir(cDir)
       return true
    catch
       return false
    done

</lang>

Ruby

<lang ruby>require 'fileutils' FileUtils.mkdir_p("path/to/dir") </lang> mkdir_p also takes an array of pathnames instead of a single pathname as an argument. mkdir_p is aliased as: mkpath, makedirs.

Scala

<lang Scala>new java.io.File("/path/to/dir").mkdirs</lang> Alternative (platform-independent) for the library function: <lang Scala>import java.io.File

def mkdirs(path: List[String]) = // return true if path was created

   path.tail.foldLeft(new File(path.head)){(a,b) => a.mkdir; new File(a,b)}.mkdir

mkdirs(List("/path", "to", "dir")) </lang>

Seed7

The library cli_cmds.s7i defines the function doMkdirCmd, which is used below.

<lang seed7>$ include "seed7_05.s7i";

 include "cli_cmds.s7i";

const proc: main is func

 begin
   doMkdirCmd(argv(PROGRAM), TRUE);
 end func;</lang>

The library cli_cmds.s7i defines also doMkdir (Make directories like the Unix mkdir command) and doMd (Make directories like the DOS md command). This functions read the parameters and options from a string. The reading is done according to Unix respectively DOS/Windows rules. The function doMkdir is used in the alternate solution below:

<lang seed7>$ include "seed7_05.s7i";

 include "cli_cmds.s7i";

const proc: main is func

 local
   var string: parameters is "";
 begin
   parameters := join(argv(PROGRAM), " ");
   doMkdir(parameters);
 end func;</lang>

Sidef

<lang ruby>Dir.new(Dir.cwd, "path", "to", "dir").make_path; # works cross-platform</lang>

Tcl

Tcl's built in file mkdir works exactly this way: <lang tcl>file mkdir ./path/to/dir</lang> If a directory cannot be made (e.g., because it would involve making a directory with the same name as an existing file) the command will throw a trappable error, as normal for Tcl commands.

UNIX Shell

Works with: Bourne Again SHell

<lang bash>function mkdirp() { mkdir -p "$1"; }</lang>

zkl

This is for Unix as zkl doesn't have a built in mkdir method. <lang zkl>System.cmd("mkdir -p ../foo/bar")</lang> The system error code is returned (0 in this case). <lang zkl>fcn mkdir(path) { System.cmd("mkdir -p "+path) }</lang>

Output:
zkl: mkdir("../foo/bar")
0
zkl: mkdir("/foo/bar")
mkdir: cannot create directory ‘/foo’: Permission denied
256