Include entire directory in python setup.py data_files

I don't know how to do that with relative paths

You need to get the path of the directory first, so...

Say you have this directory structure:

cur_directory
|- setup.py
|- inner_dir
   |- file2.py

To get the directory of the current file (in this case setup.py), use this:

cur_directory_path = os.path.abspath(os.path.dirname(__file__))

Then, to get a directory path relative to current_directory, just join some other directories, eg:

inner_dir_path = os.path.join(cur_directory_path, 'inner_dir')

If you want to move up a directory, just use "..", for example:

parent_dir_path = os.path.join(current_directory, '..')

Once you have that path, you can do os.listdir

For completeness:

If you want the path of a file, in this case "file2.py" relative to setup.py, you could do:

file2_path = os.path.join(cur_directory_path, 'inner_dir', 'file2.py') 

I ran into the same problem with directories containing nested subdirectories. The glob solutions didn't work, as they would include the directory in the list, which setup would blow up on, and in cases where I excluded matched directories, it still dumped them all in the same directory, which is not what I wanted, either. I ended up just falling back on os.walk():

def generate_data_files():
    data_files = []
    data_dirs = ('data', 'plugins')
    for path, dirs, files in chain.from_iterable(os.walk(data_dir) for data_dir in data_dirs):
        install_dir = os.path.join(sys.prefix, 'share/<my-app>/' + path)    
        list_entry = (install_dir, [os.path.join(path, f) for f in files if not f.startswith('.')])
        data_files.append(list_entry)

    return data_files

and then setting data_files=generate_data_files() in the setup() block.


import glob

for filename in glob.iglob('inner_dir/**/*', recursive=True):
    print (filename)

Doing this, you get directly a list of files relative to current directory.


karelv has the right idea, but to answer the stated question more directly:

from glob import glob

setup(
    #...
    data_files = [
        ('target_directory_1', glob('source_dir/*')), # files in source_dir only - not recursive
        ('target_directory_2', glob('nested_source_dir/**/*', recursive=True)), # includes sub-folders - recursive
        # etc...
    ],
    #...
)