Assign variables to save each directories from a folder I want to assign corresponding variables based on the name to save each directory from a folder, including its subfolders, so I can get access to the file in each folder easily. The code created by myself doesn't look concise. Any suggestions?

import os

modelFld = r'C:\model'


baseInputFld = [os.path.join(modelFld, x) for x in os.listdir(modelFld) if 'base' in x.lower()][0]

oilWellFld = [os.path.join(baseInputFld, x) for x in os.listdir(baseInputFld) if 'oilwell' in x.lower()][0]
diswaterWellFld = [os.path.join(baseInputFld, x) for x in os.listdir(baseInputFld) if 'waterwell' in x.lower()][0]
quarryFld = [os.path.join(baseInputFld, x) for x in os.listdir(baseInputFld) if 'quar' in x.lower()][0]
linearRefFld = [os.path.join(baseInputFld, x) for x in os.listdir(baseInputFld) if 'linear' in x.lower()][0]
txCountyFld = [os.path.join(baseInputFld, x) for x in os.listdir(baseInputFld) if 'county' in x.lower()][0]
tigerFld = [os.path.join(baseInputFld, x) for x in os.listdir(baseInputFld) if 'tiger' in x.lower()][0]

step1Fld = [os.path.join(modelFld, x) for x in os.listdir(modelFld) if 'step1' in x.lower()][0]
step2Fld = [os.path.join(modelFld, x) for x in os.listdir(modelFld) if 'step2' in x.lower()][0]
step3Fld = [os.path.join(modelFld, x) for x in os.listdir(modelFld) if 'step3' in x.lower()][0]
step4Fld = [os.path.join(modelFld, x) for x in os.listdir(modelFld) if 'step4' in x.lower()][0]
step5Fld = [os.path.join(modelFld, x) for x in os.listdir(modelFld) if 'step5' in x.lower()][0]
step6Fld = [os.path.join(modelFld, x) for x in os.listdir(modelFld) if 'step6' in x.lower()][0]

step1InputFld = [os.path.join(step1Fld, x) for x in os.listdir(step1Fld) if 'input' in x.lower()][0]
step2InputFld = [os.path.join(step2Fld, x) for x in os.listdir(step2Fld) if 'input' in x.lower()][0]
step3InputFld = [os.path.join(step3Fld, x) for x in os.listdir(step3Fld) if 'input' in x.lower()][0]
step4InputFld = [os.path.join(step4Fld, x) for x in os.listdir(step4Fld) if 'input' in x.lower()][0]
step5InputFld = [os.path.join(step5Fld, x) for x in os.listdir(step5Fld) if 'input' in x.lower()][0]
step6InputFld = [os.path.join(step6Fld, x) for x in os.listdir(step6Fld) if 'input' in x.lower()][0]

step1OutputFld = [os.path.join(step1Fld, x) for x in os.listdir(step1Fld) if 'output' in x.lower()][0]
step2OutputFld = [os.path.join(step2Fld, x) for x in os.listdir(step2Fld) if 'output' in x.lower()][0]
step3OutputFld = [os.path.join(step3Fld, x) for x in os.listdir(step3Fld) if 'output' in x.lower()][0]
step4OutputFld = [os.path.join(step4Fld, x) for x in os.listdir(step4Fld) if 'output' in x.lower()][0]
step5OutputFld = [os.path.join(step5Fld, x) for x in os.listdir(step5Fld) if 'output' in x.lower()][0]
step6OutputFld = [os.path.join(step6Fld, x) for x in os.listdir(step6Fld) if 'output' in x.lower()][0]
You should create functions to get rid of your repetitive logic. This is called DRY (Don't repeat yourself).

The first task you repeatedly accomplish is getting the first object in a base folder matching some string.

This can be accomplished using this function:

def find_in(root, string):
    return next(os.path.join(root, x) for x in os.listdir(root) if string in x.lower())


Instead of building the whole list and then taking only the first element, this is a generator and the first element of that generator is returned. This should save a bit of time and memory. To appreciate how much, try running these three commands and see how long they take:

&gt;&gt;&gt; next(x**2 for x in xrange(100000000)
&gt;&gt;&gt; next(x**2 for x in range(100000000)
&gt;&gt;&gt; [x**2 for x in range(100000000)][0]


(The first one uses xrange, which is like range, but returns also an object like a generator, whereas the normal range returns the full list in Python 2.7.)



The second task you accomplish is the same thing as the first, but nested once. You want the first element in a stepX folder and then get the first object containinginput or output from that folder.

For this we can use the previous function and define a second function:

def find_nested(root, step, direction):
    return find_in(find_in(root, step), direction)


After this is done we can save the results in lists, instead of separate variables. Lists are for collections of similar objects.

In addition, there is an official Python style-guide, PEP8, which you should adhere to. It recommends using lower_case_with_underscores instead of camelCase. You should also avoid abbreviating variable names. Clear and more readable is better.

Final code:

import os


def find_in(root, string):
    """
    Returns the first object in the folder `root` which matches `string`.
    Case in-sensitive.
    """
    return next((os.path.join(root, x) for x in os.listdir(root) if string in x.lower()))


def find_nested(root, step, direction):
    """Returns the `direction` object from the `step` folder in `root`."""
    return find_in(find_in(root, step), direction)


if __name__ == "__main__":    
    model_field = r'C:\model'
    root_folder = find_in(model_field, 'base')

    folders = ['oilwell', 'waterwell', 'quar', 'linear', 'county', 'tiger']
    fields = [find_in(root_folder, string) for string in folders]

    steps = ["step%i" % (i + 1) for i in range(6)]
    input_fields = [find_nested(root_folder, step, "input") for step in steps]
    output_fields = [find_nested(root_folder, step, "output") for step in steps]


In case not all stepX folders actually contain an input or output file/folder, this will raise a StopIteration. To avoid this, you can unwrap the list comprehension into an actual for loop and print the missing file:

input_fields = []
for step in steps:
    try:
        input_fields.append(find_nested(root_folder, step, "input"))
    except StopIteration:
        print "Folder", step, "has no `input` file."


And similar for the output_fields.