I want to make a shell script that updates a config file.

The file present on the server has information, like various IP addresses.

The new file has more code, from new configs added to the system, I want to be able to add these new configurations to the server file without changing what's already configured there


server file


new file


I want the resulting file to be


How would be a good way to do that? I don't want to rely on line position and such, because the actual config files are quite large and more lines could have been added to the server file.

I've tried to make a diff from the files and apply the patch, but it didn't work.

Thanks for any help.

  • 2
    This may require some config-file-specific logic. It might be worth investigating a framework such as ucf. Commented Aug 23, 2012 at 20:49

3 Answers 3


As Gilles says, you'll need to use a tool that knows about the format of your config files. For your particular example, you can use a short Python script that uses the built-in ConfigParser module.

  • First, let's say your original configuration file on the server is original.cfg:

  • Now put your changes in a new file called update.cfg:


    This file should have new or changed entries listed under the section heading where you would like them to go.

  • Then run a script like this one:

    #!/usr/bin/env python
    import ConfigParser
    config = ConfigParser.ConfigParser()
    # Read the original config file
    with open('original.cfg', 'r') as f:
    # Also read in all the changes we'd like to make
    with open('update.cfg', 'r') as f:
    # Write the full new config file out
    with open('output.cfg', 'w') as f:

There are, of course, plenty of variations on how to do this. For example, the config changes could be coded directly into the Python script rather than read from a separate update.cfg file. This should give you a good base to get started, though.


Parse them into two separate datasets with whatever program you prefer. I would use common lisp and store each config file as a nested list of lists.

And then use language tools to do the merging/patching/union/set-difference/etc. At a high level, for a one side diff, the code might look like:

  (vals A :keys 'all)
  (vals B
      (keys B)
      (keys A))))

And then write out the resulting dataset to a file.

  • Interesting. Do you have example CL code? Commented Aug 24, 2012 at 0:51
  • Not anything that will compile, other than the sketch above. I figured if you went this route, you wouldn't use common lisp, so I wanted to just convey the idea. Commented Aug 24, 2012 at 0:55
  • Ok. Just to be clear, I'm not the OP, and do know CL, so I'm interested. I see there is something like py-configparser, which might be able to do similar things to the configparser module. Commented Aug 24, 2012 at 1:02
  • Yeah; the python solutions here are much more practical. But if you can get to the point in python where you are expressing set-diff, union, intersection, etc., then I think you have a more general case of this problem solved. Which might be useful. Commented Aug 24, 2012 at 1:04
  • Ah; you said you do know CL; yeah there are XML parser packages; I've messed around with Closure XML, but this config isn't XML. I've found JSON parsers for CL, but this config isn't JSON either. I dunno' if there's a lisp package to parse this one. I'd have to do a bit of research; and if not, I'd just use python :) Commented Aug 24, 2012 at 1:11

I use the ConfigObj Python library for this. If you do this, it does require writing Python to interface with the config files. I typically have a default_conf file which has default values, and I can selectively override these settings with some other file, say user_conf

Here is the code I am currently using as an example. The second half of the function is validation, which is important, but you can ignore it to a first approximation. For usage you do

conf = get_conf()
ip = conf["ip"]

In your case, I guess the server file is the one that overrides, though more usually it is the user file which overrides the system file. That is certainly the user convention in Unix-type systems.

To write a ConfigObj object to file, to a first approximation you do (if config is your object as in the script below)

config.filename = filename

So you could modify the function below to write to a file instead of returning the config object if you want. See Writing a Config File for a little more detail.

def get_conf():
    import configobj, validate, sys
        config = configobj.ConfigObj('default_conf', configspec='conf.validate', raise_errors=True)
    except configobj.ConfigObjError:
        print "ERROR FOR CONFIG FILE 'default_conf':"
        user = configobj.ConfigObj('user_conf', configspec='conf.validate', raise_errors=True)
    except configobj.ConfigObjError:
        print "ERROR FOR CONFIG FILE 'user_conf':"

    #This is config file validation
    fdict = {'check_list_of_list_of_integers': list_of_list_of_integers}
    validator = validate.Validator(fdict)

    results = config.validate(validator, preserve_errors=True)
    if results != True:
        for entry in configobj.flatten_errors(config, results):
            # each entry is a tuple
            section_list, key, error = entry
            if key is not None:
                section_list.append('[missing section]')
            section_string = ', '.join(section_list)
            if error == False:
                error = 'Missing value or section.'
            print section_string, ' = ', error


    return config

UPDATE 16th December 2015: Something like YAML is probably a better general solution. I recommend that instead of ConfigObj. For one thing, it's more flexible.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .