Skip to end of metadata
Go to start of metadata

How to read Java properties files using bash or shell.

Method 1 - Scan through the file to get an individual property

This works well if you just want to read a specific property in a Java-style properties file. Here's what it does:

  1. Remove comments (lines that start with '#')
  2. Grep for the property
  3. Get the last value using tail -n 1
  4. Strip off the property name and the '=' (using {{cut -d "=" -f2-}) to handle values with '=' in them, as a commenter suggested).

It can also be handy to strip off the leading and trailing blanks with this sed expression:

Which makes the whole thing look like this:

Shell scripts can use this technique to set environment variables, for example:

Method 2 - Convert the properties file to a shell script, then run it

This method is good for when you want to read the whole properties file. However, it only works if the property names are valid shell variable names. For example, property names with a '.' in them will cause this to break. Here is the original article that inspired this method.

Security Note

These techniques generate shell code from the properties file, then execute the generated code. This can be a potential security issue if the properties file has hidden shell code in it. Make sure you have appropriate access control on the properties file in this case.

The steps are:

  1. Create a temp file.
  2. Stream the properties file, convert it to unix LF format (unless you are sure the file was produced on Linux).
  3. (not sure what the first 'sed' does)
  4. Double quote all the values, to preserve spaces.
  5. Source in the file. Shell should ignore Java properties file comments automatically.
  6. Erase the temp file.

Here is the code:

Method 2 reloaded - Use AWK

This method is the same as the previous one except we use an inline awk script to replace any non-alpha-digit-underscore characters in the property names with underscore. This solves the problem the previous method has when it processes properties that have '.' in the name, for example.

Some clever person could probably figure out how to do the same thing with sed, but awk works.

Steps:

  1. Create a temporary file.
  2. Stream the properties file to stdout and (optionally) filter out dos style linefeeds.
  3. Split each line using "=" as the field separator. If there are exactly two fields, then substitute the non-identifier characters with underscore in the first one, and print the second field with quotes around it.
  4. If the line doesn't have an =, or seems to have more than two values, just print it out.
  5. Source in the temporary file and delete it.

Method 2 - Using Groovy

Use this if you have to really read properties files with interpolation!

If you have Groovy installed already you can use it to read ANT-style properties files (complete with interpolation), and generate a shell file that will set all the environment variables:

This reads the properties file (the first argument) and optionally the default properties file (the second argument), and writes the shell statements to stdout. Since we're using ANT to read in the properties files, this version has a lot more functionality:

  • All the standard ANT properties will be processed.
  • ANT will interpolate the property values.

So, if we have the following properties file:

The generated shell script will contain:

Edge Case - Shell commands in property values

What happens when the properties file looks like this?

When we use the Groovy script with this file, we hit an edge case:

Uh oh! This property value could have done something very bad. We can change the Groovy script to escape any single quotes like this:

However, this may break some things. Of course, this isn't a problem if you don't embed shell commands into your properties files... with single quotes around them.

See Also

  1. Oct 11, 2010

    Anonymous

    For #1, I would use  grep '^someproperty'

    instead of  grep 'someproperty'

    That way if there is a property named "other.someproperty" it doesn't get caught in the expression.

    1. Oct 18, 2010

      Yep, that'd work.

  2. Nov 18, 2010

    Anonymous

    The suggested sed command to get the value of the property (sed 's/^.*=//') is broken if that value contains "=". That is, for a property like this:

    JAVA_OPTS=-Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000

    It will return "3600000".

    Instead you can use cut (cut -d "=" -f2-) like this:

    echo `sed '/#/d' $1 | grep $2  | tail -n 1 | cut -d "=" -f2- | sed 's/[[:space:]]//;s/[[:space:]]$//'`

    1. Nov 19, 2010

      Thanks! I've added your suggestion.

  3. Nov 25, 2010

    Anonymous

    Hi, I've found another solution elsewhere on the web (http://www.coderanch.com/t/419731/Linux-UNIX/read-properties-file-through-script)

    am I missing something your solutions have going for them or is it as easy as adding ". MyFile.properties" in the shell script? 

    1. Nov 26, 2010

      That doesn't work for me because the properties files that I'm reading have '.' in the names, which is very common for ANT properties files. So, I need to translate it into something shell can actually read. That solution may work in some simple cases where there are no special characters (for shell) in the names or values of the properties, but that's probably going to break as soon as someone adds something to the file that is fine in Java or ANT, but not in shell.

    2. Jun 26, 2012

      Anonymous

      This is useful in many cases and altough it's not to be used as a general method, for reasons mentioned by Joshua Davis, it's very short form and takes advantage of the compatibility between bash and .properties -- the way variables and comments are defined.

  4. Dec 16, 2010

    Anonymous

    It is important to take security under consideration when you are choosing a solution.  Methods 2 and 3 are actually executing the properties file... in a situation where the properties file is open for user edits, this can be a very dangerous thing, especially if the script that is executing the properties file is running as root.

    Method #1 does not actually execute any code in the properties file, it merely extracts the value of the specified property key and is therefore more secure.

    1. Dec 16, 2010

      It's true that method #1 doesn't execute any potential code in the properties file, so it's more secure if it's being used to parse properties files that are edited by non-trusted users. You definitely wouldn't want to run methods #2 and #3 as root with a properties file that came from a non-trusted user.

      In my case, the parsing code is never run as root, and the file is a 'system config' file that is only edited by trusted users.

      1. Dec 16, 2010

        Anonymous

        Hehe... you said 'trusted' users... there is no such thing! (wink)

        I just want readers of this blog entry to know the security implications of options 2 and 3. It doesn't even have to be run by root... any situation where the script can run as another user opens a security hole.

        1. Dec 16, 2010

          Yes, it's a fair point. I would say it opens a potential security hole that must be addressed in some other way. My use case is JBoss configuration and app deployment, so it has to be done by a sys admin.

          If you can't trust your sys admins not to stick shell code in a java properties file... Well... That's a whole 'nother thing. (smile)

          Actually, with the Groovy approach I'm using ANT to read the properties, so in order to exploit this you'd have to figure out something that ANT Would pass through to bash and would do some bad shell stuff. Hmmm.... Back tick?

  5. Oct 20, 2012

    Fixed a small bug in the AWK version pointed out by Kent V.:

     

    I did find it didn't work if your value had = in it.  Like

    database.url="jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=blah)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=VRAC)))"

    I think I fixed by changing

     if (NF == 2)

    to

    if (NF >= 2)