Меню Рубрики

Mkdir if not exists linux

How to mkdir only if a directory does not already exist?

I am writing a shell script to run under the KornShell (ksh) on AIX. I would like to use the mkdir command to create a directory. But the directory may already exist, in which case I do not want to do anything. So I want to either test to see that the directory does not exist, or suppress the «File exists» error that mkdir throws when it tries to create an existing directory.

How can I best do this?

15 Answers 15

Note that this will also create any intermediate directories that don’t exist; for instance,

will create directories foo , foo/bar , and foo/bar/baz if they don’t exist.

Some implementation like GNU mkdir include mkdir —parents as a more readable alias, but this is not specified in POSIX/Single Unix Specification and not available on many common platforms like macOS, various BSDs, and various commercial Unixes, so it should be avoided.

If you want an error when parent directories don’t exist, and want to create the directory if it doesn’t exist, then you can test for the existence of the directory first:

which will create the directory if it doesn’t exist, but warn you if the name of the directory you’re trying to create is already in use by something other than a directory.

Defining complex directory trees with one command

If you don’t want to show any error message:

If you want to show your own error message:

The old tried and true

will do what you want with none of the race conditions many of the other solutions have.

Sometimes the simplest (and ugliest) solutions are the best.

mkdir foo works even if the directory exists. To make it work only if the directory named «foo» does not exist, try using the -p flag.

This will create the directory named «foo» only if it does not exist. 🙂

mkdir does not support -p switch anymore on Windows 8+ systems.

Or if you want to check for existence first:

-e is the exist test for KornShell.

You can also try googling a KornShell manual.

Referring to man page man mkdir for option — p

which will create all directories in a given path, if exists throws no error otherwise it creates all directories from left to right in the given path. Try the below command. the directories newdir and anotherdir doesn’t exists before issuing this command

Correct Usage

mkdir -p /tmp/newdir/anotherdir

After executing the command you can see newdir and anotherdir created under /tmp. You can issue this command as many times you want, the command always have exit(0) . Due to this reason most people use this command in shell scripts before using those actual paths.

Источник

Linux: copy and create destination dir if it does not exist

I want a command (or probably an option to cp) that creates the destination directory if it does not exist.

21 Answers 21

(there’s no such option for cp ).

If both of the following are true:

  1. You are using the GNU version of cp (and not, for instance, the Mac version), and
  2. You are copying from some existing directory structure and you just need it recreated

then you can do this with the —parents flag of cp . From the info page (viewable at http://www.gnu.org/software/coreutils/manual/html_node/cp-invocation.html#cp-invocation or with info cp or man cp ):

Short Answer

To copy myfile.txt to /foo/bar/myfile.txt , use:

How does this work?

There’s a few components to this, so I’ll cover all the syntax step by step.

The mkdir utility, as specified in the POSIX standard, makes directories. The -p argument, per the docs, will cause mkdir to

Create any missing intermediate pathname components

meaning that when calling mkdir -p /foo/bar , mkdir will create /foo and /foo/bar if /foo doesn’t already exist. (Without -p , it will instead throw an error.

The && list operator, as documented in the POSIX standard (or the Bash manual if you prefer), has the effect that cp myfile.txt $_ only gets executed if mkdir -p /foo/bar executes successfully. This means the cp command won’t try to execute if mkdir fails for one of the many reasons it might fail.

Finally, the $_ we pass as the second argument to cp is a «special parameter» which can be handy for avoiding repeating long arguments (like file paths) without having to store them in a variable. Per the Bash manual, it:

expands to the last argument to the previous command

In this case, that’s the /foo/bar we passed to mkdir . So the cp command expands to cp myfile.txt /foo/bar , which copies myfile.txt into the newly created /foo/bar directory.

Note that $_ is not part of the POSIX standard, so theoretically a Unix variant might have a shell that doesn’t support this construct. However, I don’t know of any modern shells that don’t support $_ ; certainly Bash, Dash, and zsh all do.

A final note: the command I’ve given at the start of this answer assumes that your directory names don’t have spaces in. If you’re dealing with names with spaces, you’ll need to quote them so that the different words aren’t treated as different arguments to mkdir or cp . So your command would actually look like:

Such an old question, but maybe I can propose an alternative solution.

You can use the install programme to copy your file and create the destination path «on the fly».

There are some aspects to take in consideration, though:

  1. you need to specify also the destination file name, not only the destination path
  2. the destination file will be executable (at least, as far as I saw from my tests)

You can easily amend the #2 by adding the -m option to set permissions on the destination file (example: -m 664 will create the destination file with permissions rw-rw-r— , just like creating a new file with touch ).

Shell function that does what you want, calling it a «bury» copy because it digs a hole for the file to live in:

Here’s one way to do it:

dirname will give you the parent of the destination directory or file. mkdir -p `dirname . ` will then create that directory ensuring that when you call cp -r the correct base directory is in place.

The advantage of this over —parents is that it works for the case where the last element in the destination path is a filename.

And it’ll work on OS X.

install -D file -m 644 -t /path/to/copy/file/to/is/very/deep/there

with all my respect for answers above, I prefer to use rsync as follow:

Just to resume and give a complete working solution, in one line. Be careful if you want to rename your file, you should include a way to provide a clean dir path to mkdir. $fdst can be file or dir. Next code should work in any case.

Simply add the following in your .bashrc, tweak if you need. Works in Ubuntu.

E.g If you want to copy ‘test’ file to destination directory ‘d’ Use,

mkcp will first check if destination directory exists or not, if not then make it and copy source file/directory.

This does it for me

I wrote a support script for cp, called CP (note capital letters) that’s intended to do exactly this. Script will check for errors in the path you’ve put in (except the last one which is the destination) and if all is well, it will do an mkdir -p step to create the destination path before starting the copy. At this point the regular cp utility takes over and any switches you use with CP (like -r, -p, -rpL gets piped directly to cp). Before you use my script, there are a few things you need to understand.

  • all the info here can be accessed by doing CP —help. CP —help-all include’s cp’s switches.
  • regular cp won’t do the copy if it doesn’t find the destination path. You don’t have such a safety net for typos with CP. You’re destination will be created, so if you misspell your destination as /usrr/share/icons or /usr/share/icon well that’s what’s going to be created.
  • regular cp tends to model it’s behavior on the existing path: cp /a/b /c/d will vary on whether d exists or not. if d is an existing folder, cp will copy b into it, making /c/d/b. If d doesn’t exist, b will be copied into c and renamed to d. If d exists but is a file and b is a file, it will be overwritten by b’s copy. If c doesn’t exist, cp doesn’t do the copy and exits.

CP doesn’t have the luxury of taking cues from existing paths, so it has to have some very firm behavior patterns. CP assumes that the item you’re copying is being dropped in the destination path and is not the destination itself (aka, a renamed copy of the source file/folder). Meaning:

  • «CP /a/b /c/d» will result in /c/d/b if d is a folder
  • «CP /a/b /c/b» will result in /c/b/b if b in /c/b is a folder.
  • If both b and d are files: CP /a/b /c/d will result in /c/d (where d is a copy of b). Same for CP /a/b /c/b in the same circumstance.

This default CP behavior can be changed with the «—rename» switch. In this case, it’s assumed that

  • «CP —rename /a/b /c/d» is copying b into /c and renaming the copy to d.

A few closing notes: Like with cp, CP can copy multiple items at a time with the last path being listed assumed to be the destination. It can also handle paths with spaces as long as you use quotation marks.

CP will check the paths you put in and make sure they exist before doing the copy. In strict mode (available through —strict switch), all files/folders being copied must exist or no copy takes place. In relaxed mode (—relaxed), copy will continue if at least one of the items you listed exists. Relaxed mode is the default, you can change the mode temporarily via the switches or permanently by setting the variable easy_going at the beginning of the script.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

  • Контур экстерн на mac os
  • Конструктор сайтов для mac os
  • Консольные команды mac os x
  • Коннект менеджер мтс для mac os sierra
  • Конвертировать видео mac os