4

I have a folder which contains some folders, these folder are moved very often so I made a script to see if they exist, and if not then create them. This is what I did to (which I though would) achieve it:

if [ ! -f "$DIR/0folder" ]
then
mkdir "$DIR/0folder"
fi

But, even if 0folder already exists, it still tries to make it which mkdir tells me. Like here;

mkdir: /Allfoldersgoeshere/subfolder/0folder: File exists

Why? It should just ignore it because it already exists?

3
  • 1
    Have you tried to replace -f by -d? Commented Apr 7, 2015 at 20:38
  • 3
    THe simpel answer is mkdir -p "$dir/0folder" It will create if it doesn't exist otherwise nothing happens. Commented Apr 7, 2015 at 20:56
  • @val0x00ff: That should be an answer Commented Apr 8, 2015 at 0:50

5 Answers 5

12

The -f in your test is checking if FILE exists and is a regular file. What you need is -d to test if FILE exists and is a directory.

if [ ! -d "$DIR/0folder" ]
then
mkdir "$DIR/0folder"
fi

It is not mandatory to check if a directory exists though. According to the man page of mkdir we see the following

man mkdir | grep -A1 -- -p

   -p, --parents
          no error if existing, make parent directories as needed

However, if FILE exists and is a regular file mkdir -p will fail with

mkdir: /Allfoldersgoeshere/subfolder/0folder': Not a directory.  

In this scenario handling the file that is expected to be a directory will be necessary before directory creation.

4
  • Oh, so -f is for files and -d for directories? Commented Apr 7, 2015 at 20:39
  • 1
    Yes, man test will show the test options. Commented Apr 7, 2015 at 20:40
  • 3
    And if you don't care what sort of thing it is, you can use -e. Commented Apr 7, 2015 at 23:31
  • @val0x00ff - Thank you for adding the mkdir -p info. Commented Apr 8, 2015 at 18:30
3

From the manual (man bash) under CONDITIONAL EXPRESSIONS:

-f file
          True if file exists and is a regular file.

-d file
          True if file exists and is a directory.

So, to check for the existence of a directory (not a file)...

if [[ ! -d "$DIR/0folder" ]] ; then
    mkdir "$DIR/0folder"
fi
3

Neither -d or -f is useful here for robust tests - because they're just opposite sides of the same coin.

touch file; [ ! -d file ] && mkdir file
mkdir: cannot create directory ‘file’: File exists

See? Better would be [ -e ... ] || mkdir ... to check for existence, which would at least save on the error above, but even that has its issues - like race conditions or not creating parents as needed or unresolved symlinks.

if    [ ! -e "$DIR/0folder" ] && 
      [ ! -L "$DIR/0folder" ] 
then  mkdir -- "$DIR/0folder"
fi

...is closer but still racy and still assumes all parents exist as well.

Probably you could work out a sure test if you needed to, but you really don't. You can get atomic directory creation w/ mkdir -p and test its return. There aren't too many standard shell tools which offer atomic fs ops - it's best we take advantage of those that do.

1
  • +1 for presenting a more complete answer and explanation than mine. Commented Apr 8, 2015 at 16:59
2

Read the manual. The -p option will make a directory and intermediate directories as required if it doesn't exist or silently fail. Assuming that you are not processing thousands of files then you could just do mkdir -p "${DIR}/0folder or if you feel the need to test then

 [ -d "${DIR}/0folder" ] || mkdir -p "${DIR}/0folder"
2
  • 2
    The -d test before mkdir -p is rather useless. If it is useful to know whether or not a directory was created, just test mkdir exit status: 0 means a directory was created. That said. +1 for mkdir -p... to nullify the notification when exit status is non-zero, mkdir -p dir/dir 2>/dev/null Commented Apr 8, 2015 at 0:18
  • 1
    @Peter.O - possibly worse than useless - it implies the test is useful, but it is not. Commented Apr 8, 2015 at 17:19
1

You're doing: if the $DIR/0folder doesn't exist, make a directory with that name.

Just change -f (file) by -d (directory).

That should solve your problem, now you could be interested on some tips that people had given here but that is apart.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.