Kick off a Cygwin script from a windows bat file with a different working directory

I recently created a script that would pull the Tomcat log files from a group of web servers and then run my 95th percentile awk script to generate a summary of response times for the 100 most popular pages.  I wanted to run this as a nightly scheduled job so that I could have a report each day, but the job needed to run from a Windows machine.

Cygwin allows my linux script to run on a windows box, but I needed a way to kick off my Cygwin shell script.  After googling around I found some instructions on how to invoke a bash shell script through Cygwin from a command-line.  The bat file that starts up Cygwin is pretty simple:

1
2
3
4
5
6
@echo off

C:
chdir C:cygwinbin

bash --login -i

By creating your own version, you can use the “-c” switch for bash to have it execute your own shell script and then exit:

1
2
3
4
5
6
@echo off

C:
chdir C:cygwinbin

bash --login -i "/cygdrive/d/MyDirectory/MySubDirectory/my_script.sh"

This was a good start, but it left me with a new problem.  My shell script assumed that the working directory was the same directory it was in, and it expected to have various awk scripts and other support files to be locally available.  When my shell script was invoked by my bat file, the working directory was in the Cygwin startup folder, and my script was getting “file not found” errors.

I needed to modify my shell script so that it would change the working directory to be the directory the script was located in.  A bash shell script can figure out its own name using a special parameter, $0.  If the script is being executed from a different directory, then it will contain the path that was used.  For example, if I executed “MyDirectory/MySubDirectory/my_script.sh arg1 arg2”, then $0 would be “MyDirectory/MySubDirectory/my_script.sh”.

I can now use the “dirname” command, which will take a string with a path and just return the directory name.  So, if I call “dirname MyDirectory/MySubDirectory/my_script.sh”, it will output “MyDirectory/MySubDirectory”.

I can now put these pieces together to automatically change to the script’s local directory like this:

1
2
3
4
5
6
#!/bin/bash

# switch the working directory to the script's local directory
targetdir=$(dirname "$0")
echo $targetdir
cd "$targetdir"

UPDATE: Duncan Smart has made some nice enhancements to the Windows bat file portion of the script, creating a much more versatile script that pass along command line arguments and automatically handle path mapping.  

This entry was posted in Uncategorized and tagged , , , . Bookmark the permalink.

6 Responses to Kick off a Cygwin script from a windows bat file with a different working directory

  1. duncansmart says:

    Tip: use chdir/cd’s /d switch to change directory (if necessary) e.g. cd /d c:\cygwin\bin. Although you could just do the following too:@C:\cygwin\bin\bash –login -c “/cygdrive/d/MyDirectory/MySubDirectory/my_script.sh”No messing with the working dir.(The @ at the start of a line prevents echoing it without needing echo off)

  2. Jeremy Rothman-Shore says:

    I’m not sure I follow your suggestion, Duncan. The part of the script you are referring to is just part of the original cygwin bat shell written by whoever wrote cygwin. My modification is around getting cygwin to launch my shell script (the part after the -c switch), and then getting that shell script to figure out what directory it is in and change the working directory there.

  3. duncansmart says:

    I’m really just saying that 4 lines of batch file can be just one! I think I may have a niftier solution anyway. I’ll blog it.

  4. Jeremy Rothman-Shore says:

    Awesome, Duncan. Your knowledge of the windows scripting shell is most impressive!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s