Create folder in batch script and ignore if it exists

45,853

Solution 1

A standard method to create a directory structure is:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "Directory=mydir\subdir 1\subdir 2"

md "%Directory%" 2>nul
if not exist "%Directory%\*" (
    echo Failed to create directory "%Directory%"
    pause
    goto :EOF
)

rem Other commands after successful creation of the directory.
endlocal

By default command extensions are enabled and delayed expansion is disabled. The batch code above explicitly sets up this environment.

The command MD creates the complete directory structure to specified directory with enabled command extensions.

MD outputs an error if the directory already exists. This might be useful to inform a user entering the command manually about a possible mistake in entered directory path as it could be that the user wanted to create a new directory and has entered just by mistake the name of an already existing directory.

But for scripted usage of command MD it is often a problem that this command outputs an error message if the directory to create already exists. It would be really helpful if command MD would have an option to not output an error message in case of directory to create already existing and exiting with return code 0 in this case. But there is no such option.

The solution above creates the directory and suppresses a perhaps output error message with redirecting it from handle STDERR to device NUL.

But the creation of the directory could fail because of invalid character in directory path, drive not available (on using full path), there is anywhere in path a file with name of a specified directory, NTFS permissions don't permit creation of the directory, etc.

So it is advisable to verify if the directory really exists which is done with:

if not exist "%Directory%\*"

It is important that the directory path ends now with \* or at least with a backslash. Otherwise it could be possible for the example that there is a file with name subdir 2 in directory mydir\subdir 1 which on usage of the condition if not exist "%Directory%" would evaluate to false although there is no directory subdir 2.

It is of course also possible to do the directory check first and create the directory if not already existing.

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "Directory=mydir\subdir 1\subdir 2"

if not exist "%Directory%\*" (
    md "%Directory%"
    if errorlevel 1 (
        pause
        goto :EOF
    )
)

rem Other commands after successful creation of the directory.
endlocal

The user can see now the error message output by command MD if the directory structure could not be created explaining briefly the reason.

This batch code could be written more compact using operator ||:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "Directory=mydir\subdir 1\subdir 2"

if not exist "%Directory%\*" md "%Directory%" || (pause & goto :EOF)

rem Other commands after successful creation of the directory.
endlocal

For details about the operators || and & read the answer on Single line with multiple commands using Windows batch file.

The command ENDLOCAL is not used before goto :EOF because this command requires also enabled command extensions. Windows command interpreter executes this command implicit on leaving execution of the batch file.

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • echo /?
  • endlocal /?
  • goto /?
  • if /?
  • md /?
  • pause /?
  • set /?
  • setlocal /?

Read also the Microsoft article about Using Command Redirection Operators.

Solution 2

You need to check the path and create if it doesn't exist

if not exist "mydir\subdir" md "mydir\subdir"

Or you can also suppress the error message by redirecting stderr

md "mydir\subdir" 2>NUL

You don't need to run mkdir mydir first because

Command extensions, which are enabled by default, allow you to use a single md command to create intermediate directories in a specified path.

https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/md

See also https://ss64.com/nt/md.html

Share:
45,853
steavy
Author by

steavy

student

Updated on July 05, 2022

Comments

  • steavy
    steavy almost 2 years

    How do I create folder (and any subfolders) in batch script? But the important thing is that, if the folder (or any subfolders) already exists, it should not return error.

    For example, something like this:

    • mkdir mydir - success(directory is now created)
    • mkdir mydir\subdir - success(now mydir contains subdir)
    • mkdir mydir - success(folder already exists, should not throw an error)
    • mkdir mydir\subdir - success(folders already exists, should not throw an error)

    What I actually need is just to ensure that the folder structure exists.

    • Eryk Sun
      Eryk Sun almost 7 years
      mkdir mydir\subdir will create mydir if it doesn't already exist. An error occurs if the final path component already exists, or if any component is a file instead of a directory.
    • steavy
      steavy almost 7 years
      @eryksun It is great that it creates mydir if it doesn't already exist. But I strongly don't want to have an error if final path component already exists.
  • Eryk Sun
    Eryk Sun almost 7 years
    You can't ignore the error when one of the path components is a file instead of a directory. That can't be allowed to silently pass as successful. For example, mkdir name1\name2\name3_is_a_file\name4.
  • steavy
    steavy almost 7 years
    I find those two solutions too complicated for such a simple task as directory creation. They are more like workarounds. I'm interested if there is a simple solution like some configuration flag or different command that has desired behavior.
  • dbenham
    dbenham almost 7 years
    @steavy - If you find these solutions too complicated, then you should abandon working in batch now.
  • dbenham
    dbenham almost 7 years
    @eryksun - Interesting edge case. File names without an extension are rare, but I see your point. It is a shame that the ERRORLEVEL is the same for existing file and existing folder.
  • steavy
    steavy almost 7 years
    @Mofi md mydir\subdir 2>NUL solution doesn't fit me because I don't want to suppress all possible errors. I just don't want to get an error if such folder already exists. Just like you wrote "It just matters if the directory exists after the command line was executed'. If there was some system error that prevented creation of the folder I would still like to get an error because it would indicate that my folder was not created. But if folder was already there - I just don't care, I'm good to go.Do you see my point?
  • steavy
    steavy almost 7 years
    Thanks for the expanded answer. Actually, it's a shame that such a common operation(in scripting) should be done with so many hassle, while it could have just accepted a simple flag(for example).
  • ndtreviv
    ndtreviv over 3 years
    @steavy Agreed! Unix: mkdir -p path/to/create One level exists? Move on. Windows: entire bat file just to do it. Ppfff
  • pelos
    pelos about 3 years
    my job still fail even with 2>nul still raise an error inside jenkins
  • phuclv
    phuclv about 3 years
    @pelos then there are other issues like permission that you need to check by running md without redirecting stderr. See Mofi's answer above
  • pelos
    pelos about 3 years
    thanks @phuclv redirecting to nul, if the folder was there still raise errorcode1 and that changed the whole workflow, i was able to do bat "if not exist artifact md artifact" and that solve it =)