How to read Java properties files using bash or shell.
Contents |
|---|
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:
- Remove comments (lines that start with '#')
- Grep for the property
- Get the last value using
tail -n 1 - 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:
- Create a temp file.
- Stream the properties file, convert it to unix LF format (unless you are sure the file was produced on Linux).
- (not sure what the first 'sed' does)
- Double quote all the values, to preserve spaces.
- Source in the file. Shell should ignore Java properties file comments automatically.
- 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:
- Create a temporary file.
- Stream the properties file to stdout and (optionally) filter out dos style linefeeds.
- 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.
- If the line doesn't have an =, or seems to have more than two values, just print it out.
- 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:
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
- The '.properties' file format
- Remove comments using sed
- http://www.mslinn.com/blog/index.php/archives/2004/11/03/reading-java-properties-files-from-bash
- Here is a solution that works in some special cases, but not in general: http://www.coderanch.com/t/419731/Linux-UNIX/read-properties-file-through-script#2347487
- StackExchange question - http://stackoverflow.com/questions/1682442/reading-java-properties-file-from-bash
12 Comments
Hide/Show CommentsOct 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.
Oct 18, 2010
Joshua Davis
Yep, that'd work.
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:]]$//'`
Nov 19, 2010
Joshua Davis
Thanks! I've added your suggestion.
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?
Nov 26, 2010
Joshua Davis
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.
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.
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.
Dec 16, 2010
Joshua Davis
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.
Dec 16, 2010
Anonymous
Hehe... you said 'trusted' users... there is no such thing!
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.
Dec 16, 2010
Joshua Davis
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.
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?
Oct 20, 2012
Joshua Davis
Fixed a small bug in the AWK version pointed out by Kent V.: