hackdaddy has asked for the wisdom of the Perl Monks concerning the following question:

Because my Perl utility script has external dependencies on Unix commands, how can I be sure that the Unix commands will be available in the location I expect them to be? How can I be sure that they will be the versions I expect? How can I be sure the Unix command is not an alias?
/bin/echo /bin/which /bin/df /bin/uname /bin/awk /bin/ls sqlplus grep find gtar
On the Windows platform, there is a standard Windows API for querying the machine's hardware and configuration. When scripting in a Unix environment, how does the programmer ensure standard results when using external Unix commands?

Replies are listed 'Best First'.
Re: External Dependencies on Unix Commands
by Abigail-II (Bishop) on Jun 07, 2002 at 18:42 UTC
    To make sure they are in the place you expect them to be, you could make use of the -x function. However, don't expect all those tools to be in /bin. You'll find some of them in /bin, others in /usr/bin. Or in both. And sometimes, /bin is just a symlink to /usr/bin.

    sqlplus and gtar should not be found in /bin or /usr/bin. But you may however just depend on the users PATH. Aliases don't play a role - if a shell is being used, it will be the Bourne shell, and that doesn't have aliases.


      some systems (redhat linux for one) don't have a real bourne shell, just a symlink to bash, which does have aliases.
Re: External Dependencies on Unix Commands
by perigeeV (Hermit) on Jun 07, 2002 at 19:22 UTC

    Welcome to the age old headache of the shell programmer. Each utility can/will be in different locations among differing OS's, and their command switches and default output will certainly be different. I think this was a reason Perl became popular as a cross-OS scipting language, no?

    Perhaps look into the Perl Power Tools, which are pure-Perl versions of many Unix utilities.

Re: External Dependencies on Unix Commands
by rah (Monk) on Jun 08, 2002 at 03:43 UTC
    The location, availability, and versions of some of these tools is precisely why cross-platform shell scripting is so tricky. Also, as perigeeV observes, a big factor in the emergence of Perl as a cross OS tool. Most of the tools you describe are standard UNIX commands and are likely to be found in /bin or /usr/bin. Both should be in your path with a standard shell login on most UNIX systems. echo is likely to be found as a shell built-in.

    You are correct about "which" only working within your path. However, for most of these, that would be a safe assumption. sqlplus and gtar are more problematic, as they may not be installed on your target system at all, or might be found other places (like /usr/local/bin). The only sure way to know is to check for yourself before-hand (assuming shell access) or ask your sys admin. Shell could be any number of varieties from Bourne to Korn to Bash to POSIX YMMV regarding aliases and built-ins. Again, your sys admin is the definitive source.

    awk might be one of the most troublesome as there are significant differences in versions and it is not uncommon to have multiple versions on the same system (awk, gawk, nawk...). One of our systems had both awk and nawk and each was referenced by a symlink named awk at different places. Made for real interesting behavior if you had a dot in your path!

    I second the notion of using a pure perl solutions where possible. Do you need echo when you have print, printf, and formats? Do you need grep when you have, arguably, more powerful regex capabilities within Perl? Most(all?) of what you listed has a pure Perl counterpart.

    You might also want to take a look at Heiner's SHELLdorado. It is an excellent refernece for shell tools that includes info and or links covering awk version compatibility and cross-platform shell scripting.

Re: External Dependencies on Unix Commands
by robobunny (Friar) on Jun 07, 2002 at 18:39 UTC
    you can always avoid aliases by giving the full path to the command. you can check to see if the command is where you think it is (and executable) with the -x file test. of course, you should probably just try to do whatever you are doing with the commands inside your perl script instead. if you are having trouble implementing some behavior inside your perl script, this is the place to ask :)
Re: External Dependencies on Unix Commands
by hackdaddy (Hermit) on Jun 07, 2002 at 21:49 UTC
    Update: Please do not take this as a flame against Unix. I personally prefer Unix, although I sometimes long for a well organized UNIX filesystem or standardized system to access it. See "UNIX System Administration Handbook", 3rd Edition, p. 65.
Re: External Dependencies on Unix Commands
by runrig (Abbot) on Jun 08, 2002 at 17:01 UTC

    Do you really need to access all those commands? E.g. perl can do anything awk can do, you might use DBI/DBD::Oracle instead of sqlplus, File::Find instead of find; opendir, readdir, and maybe stat or one of the -X operators (I see more code that does 'ls -l' and cuts out the file size than I care to) instead of ls; @INC and -x instead of which...

    I do write scripts occasionally which access unix commands, but the last time I did that, the command was 'patch', and there didn't seem to be anything on CPAN, and it saved alot of perl programming. And maybe if you have a sqlplus script which outputs a formatted report, I might keep that, since it would be alot of work to redo it in perl. Otherwise I'd look at what you really need.

Re: External Dependencies on Unix Commands
by rbc (Curate) on Jun 07, 2002 at 21:27 UTC
    You might want to know about the which command.
      Thanks for your reply. I am familiar with the 'which' command; however, the file has to be on the path for which to find it.
      NAME which - locate a command; display its pathname or alias SYNOPSIS which [ filename ... ] DESCRIPTION which takes a list of names and looks for the files which would be executed had these names been given as commands. Each argument is expanded if it is aliased, and searched for along the user's path. Both aliases and path are taken from the user's .cshrc file.