1

I have a bash script that I use to call a java class and I pass two arguments to this java class. The first argument ($1) is the string that I pass and it contains someone's name. The second argument ($2) is the previous month as a two digit number (also passed in by the user).

So the java class is called like this:

 java -DCONFIG_DIR=... com.example.myapp.grades.gradingProcess $1 $2

However, now, I don't want the user to pass in the second argument and instead, I want the script to determine the month.
Can I do something like this?

      month=`date +'%m' -d 'last month'`

 java -DCONFIG_DIR=... com.example.myapp.grades.gradingProcess $1 $month

And when I run my script, it'll be something like this: ./myscript.sh 'John' and not pass in a two-digit month since I'm already doing it inside the script?

Or is that not the correct way to go about it? Sorry if this seems like an elementary question, I'm still trying to get used to bash scripts.

Thank you?

user3266259
  • 369
  • 3
  • 8
  • 22
  • 8
    Yes, that should work. One suggestion: if a person's name can have a space in it, you'll want to put `$1` in double quotes so it gets passed as a single token. (The user will also have to use double quotes.) – Juan Tomas Jul 25 '16 at 21:36
  • 1
    @JuanTomas -- Not just *if* you expect spaces; if you do proper quoting even when you don't expect to need it, you'll avoid bugs when your expectations were incorrect. (I've actually seen a massive data loss event after someone chose not to quote a variable expansion that was expected to only contain filenames matching `[0-9a-f]{24}` -- a buffer overflow dumped a string containing a whitespace-surrounded asterisk into a name, a poorly-written script tried to delete that file, and calamity ensued). – Charles Duffy Jul 25 '16 at 23:06
  • @JuanTomas, so I don't need to put $month in quotes, correct? Also, I know for a fact that I will only be passing in one word names (no spaces), but thanks for the heads up! I'll keep that in mind. – user3266259 Jul 26 '16 at 02:09
  • You should basically quote everywhere unless you know why not. See also [When to wrap quotes around a variable](http://stackoverflow.com/questions/10067266/when-to-wrap-quotes-around-a-variable). – tripleee Jul 26 '16 at 02:13

2 Answers2

2

If you are looking for how to supply a default value in the shell, there is an operator for that.

month=${2-$(date -d 'last month' +%m)}

java -stuff "$1" "$month"

Now, if there was a value in $2, month will be set to that; otherwise, the default will be used. The notation ${variable-value} supplies the value of variable or, if it is unset, the text value. (There is also ${variable:-value} which produces value if variable is set but empty as well.)

(This could be inlined into the java command line, even, though using a variable to break it up is probably better for legibility.

java -stuff "$1" "${2-$(date -d 'last month' +%m)}"

Notice also how you basically always put user-supplied variables in double quotes.)

tripleee
  • 175,061
  • 34
  • 275
  • 318
0

A few thoughts: time zone, leading zero, and leveraging Java rather than bash.

Time zone

Determining the current month requires a current date. Determining the current date requires a time zone.

For any given moment the date varies around the globe. For example, a few minutes after midnight in Paris is a new day while still “yesterday” in Montréal.

When you do not specify a time zone, a current default time zone is implicitly applied. Be aware that the default can change at any moment. And depending on the default means your code is relying on an externality outside your direct control. And it means results will vary.

So around the ending/beginning of the month you could be getting the wrong month number determining on the time zone in play.

Leading zero can mean octal in Java

The %m you are using produces two digits. Single digit month numbers will have a leading zero. Ex: 09

Be aware that in some situations in Java a number with a leading zero is interpreted as a octal number (base 8) rather than a decimal number (base 10).

Let Java do the work

I suggest it makes more sense to let the Java class do the work of determining the previous month. The bash line should be passing the desired/expected time zone rather than the month, if anything.

ZoneId zoneId = ZoneId.of( "America/Montreal" ) ;
int previousMonthNumber = LocalDate.now( zoneId ).minusMonths( 1 ).getMonthValue() ;

Tip: In Java, even better to use an object from the Month enum rather than a mere integer. Makes your code more self-documenting, type-safe, and guarantees valid values.

Month month = LocalDate.now( zoneId ).minusMonths( 1 ).getMonth() ;
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • 1
    It is trivial to specify a time zone for the `date` command; just set `TZ` in the command line. (Eg. `TZ=America/Lima date +%-m -d'last month'`). – rici Jul 26 '16 at 01:00
  • It's overtly dramatic to say "the default can change at any moment". If you are running a shell, the environment is created before the shell initializes, and will stay put until the shell exits. If the admin changes the global default settings in the meantime, you will only notice when you start a new shell. – tripleee Jul 26 '16 at 02:24
  • My point is that implicitly relying on the default time zone has two risks: (a) it is an externality outside of your control (a fact, not overly dramatic when it can completely change your results), and (b) many programmers do not know or think about time zone in general and even less so with determining a month. – Basil Bourque Jul 26 '16 at 05:36