Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

In my project, I am using Mercurial and a folder in when the user can upload file. But since the user will upload files, the folder is empty.

I don't know how I can add this folder to my project without putting any file inside.

Do you know how I can do ?

share|improve this question

3 Answers 3

up vote 35 down vote accepted

Mercurial is only keeping track of files, not directories.

One of the solution is to add a .emtpy file in your repository :

$ touch uploads/.empty
$ hg add uploads/.empty
share|improve this answer
Yes, that is indeed the correct solution: Mercurial is only keeping track of files, not directories. Another solution is to create the empty directories when you deploy your software. –  Martin Geisler Dec 21 '09 at 23:23
I'm thinking naming it .hgempty might give a better clue as to what it's for –  User Oct 9 '12 at 20:40
Yes or .hgkeep –  Natim Oct 10 '12 at 7:28
Might as well go for verbose: .hgkeepifempty :) –  Daniel Sokolowski Feb 25 '13 at 19:40
.hgkeepemptyfolder –  Daniel Sokolowski yesterday

I have created a python script that automates the process of creating/deleting those files.

Here's the script's source: http://pastebin.com/inbYmMut


# Copyright (c) 2011 Ernesto Mendez (der-design.com)
# Dual licensed under the MIT and GPL licenses:
# http://www.opensource.org/licenses/mit-license.php
# http://www.gnu.org/licenses/gpl.html

# Version 1.0.0
# - Initial Release

from __future__ import generators
import sys
from optparse import OptionParser
import os

def main():
    # Process arguments

    if len(args) > 1:
        parser.error('Too many arguments')

    elif len(args) == 0:
        parser.error('Missing filename')

    if not os.path.exists(options.directory):
        parser.error("%s: No such directory" % options.directory)

    filename = args[0]

    # Create generator

    filetree = dirwalk(os.path.abspath(options.directory))

    # Walk directory tree, create files

    if options.remove == True:

        removed = ['Removing the following files: \n']
        cmd = "rm"

        for file in filetree:
            if (os.path.basename(file) == filename):
                cmd += " %s" % fixpath(file)

        if cmd != "rm":
            for f in removed: print f
            print "No files named '%s' found" % filename

    # Walk directory tree, delete files


        created = ["Creating the following files:\n"]
        cmd = "touch"

        for file in filetree:
            if (os.path.isdir(file)):
                created.append("%s%s" % (file, filename))
                cmd += " " + fixpath("%s%s" % (file, filename))

        if cmd != "touch":
            for f in created: print f
            print "No empty directories found"

def dirwalk(dir, giveDirs=1):
    # http://code.activestate.com/recipes/105873-walk-a-directory-tree-using-a-generator/
    for f in os.listdir(dir):
        fullpath = os.path.join(dir, f)
        if os.path.isdir(fullpath) and not os.path.islink(fullpath):
            if not len(os.listdir(fullpath)):
                yield fullpath + os.sep
                for x in dirwalk(fullpath):  # recurse into subdir
                    if os.path.isdir(x):
                        if giveDirs:
                            yield x
                        yield x
            yield fullpath

def wrap(text, width):
    return reduce(lambda line, word, width=width: '%s%s%s' % (line, ' \n'[(len(line)-line.rfind('\n')-1 + len(word.split('\n', 1)[0] ) >= width)], word), text.split(' ') )

def fixpath(p):
    return shellquote(os.path.normpath(p))

def shellquote(s):
    return "'" + s.replace("'", "'\\''") + "'"

def init_options():
    global parser, options, args
    parser = OptionParser(usage="usage: %prog [options] filename", description="Add or Remove placeholder files for SCM (Source Control Management) tools that do not support empty directories.")
    parser.add_option("-p", "--path", dest="directory", help="search within PATH", metavar="PATH")
    parser.add_option("-r", "--remove", dest="remove", action="store_true", help="remove FILE from PATH, if it's the only file on PATH")

    (options, args) = parser.parse_args()

if __name__ == '__main__':
share|improve this answer
The link is dead. –  Natim Oct 10 '12 at 7:30
True, updated link... –  der Oct 11 '12 at 22:20
host it on bitbucket (or ) github , old pastebin is old –  V3ss0n Dec 10 '12 at 15:28

Coming from git I just had to figure this out myself, I use .hgkeep. Depending on your use case, your mileage may vary with the following solution.

Usually when I want to keep a folder, I truly want it empty (ie. logs) and not allow any additional files added to that path. This is one way you can do that in the project's .hgignore file:


The rule will ignore everything on log/** and tmp/** except the .hgkeep file. The reason why this rule is important, is that any files in that folder (ie. log/mylog.log will look like a new non-versioned file in your hg status if you don't ignore.

share|improve this answer
Please read the question again carefully. Your answer does not answer the original question, which asked "how to add an empty folder" not "How to ignore a folder" –  DavidPostill Jun 26 at 22:18

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.