Using Perl with Cygwin

Some of us are using PERL on our Windows boxes to process data, etc. Many are also using cygwin to have a UNIX-like environment. This page offers some tips on getting ActiveState's PERL to work within a cygwin environment.

First, many folks recommend using a cygwin version of Perl if you are going to use cygwin as it avoids some of the problems I have addresed below. That may be a viable solution for you. I had already invested time in building my tools based on ActiveState (which has a richer set of add-ins, like modules). The cygwin folks also recommend getting a cygwin implementation of Xemacs.

The Problem

The problem basically boils down to the fact that cygwin attempts to offer a UNIX like file-system structure where absolute path names start with / instead of a windows style (e.g. c:). ActiveState's perl does not understand this UNIX style names. The very quick work around which I used for a long time was to always call perl scripts with absolute, windows-style path names (so cygwin does no conversion.) That is:
d:/parris/perl/stats.pl
works but
stats.pl
doesn't, even though d:/parris/perl is in the path. When you try to run a script relying on the #!c:/perl/bin/perl.exe syntax to specify the program that should process the script the shell (in this case cygwin's bash) effectively executes a command like:
c:/perl/bin/perl.exe absolute_script_name
If you are running from DOS everything is ok as this looks like:
c:/perl/bin/perl.exe d:/parris/perl/stats.pl
But with cygwin it looks like:
c:/perl/bin/perl.exe /cygdrive/d/parris/perl/stats.pl
and Perl balks with "no such file" because it can't resolve this pathname.

The Solution

To fix this problem, I use an intermediate shell script instead of the perl exectuable which takes the filename passed, converts it to a windows style pathname and then calls perl to process the script. The first line of my perl scripts looks like:
#!/usr/local/bin/perl
and /usr/local/bin/perl looks like:
#!/bin/sh

# This is necessary to make perl work with cygwin.  Cygwin passes
# "cygwin style" paths to the program in the #! statement and ActiveState
# perl does not know what /cygwin/d/... means.  

# So, we put #!/usr/local/bin/perl in the perl script and this is called
# This routine translates the path name to something of type d:/

args=""
while [ $# -gt 0 ]
do
    var=$1
    shift
    
    if test "`echo $var | grep '/'`" = "$var" 
    then
	# cygpath does the /cygwin/d/ to d:/ conversion
	var=`cygpath -w $var`

	# but then we have to swap \ for / (extra \ needed because the
	# shell makes a first pass at removing the \.
	var=`echo "$var" | sed 's/\\\/\\//g'`
    fi
    args="$args $var"
    
done
# finally the command is to call perl with the name of the script and the args.
cmd="c:/perl/bin/perl.exe $args"
$cmd 

This uses the cygwin command, cygpath to convert to a windows style pathname and then convers \ to / before calling perl. This script could certainly be a lot more robust but it gets the job done for me.


Other DiRT documents
Author: Mark Parris