Dr. Mark Humphrys

School of Computing. Dublin City University.

Home      Blog      Teaching      Research      Contact

Search:

CA249      CA318      CA425      CA651

w2mind.computing.dcu.ie      w2mind.org


Writing short utilities in other languages

You can of course write short command-line-driven utilities and CGI scripts in any programming language.



C / C++



Compiling a C++ program in UNIX / Linux

"Hello World" program

 edit prog.cxx
 g++ prog.cxx
This creates a binary executable file called   a.out  
To make the output a file called   prog   do this:
 g++ prog.cxx -o prog
You may need to:   chmod +x prog  
Then run:
 prog (args)





Accessing the command-line from C++

In a HLL, calling other programs (and access to the command-line in general) is usually more awkward than in a command-line-oriented script.
In C/C++ you use the system() call:

  #include <stdlib.h>

  main()
  {
   system ( "rm file7.txt" );
  }
which is more complex than the Shell:
  rm file7.txt
You also have to compile the program, and keep track of 2 files - the source and the binary. In Shell, there is only 1 file.
Also, the above is alright if filenames are static. But consider where the file name is variable. In Shell:
  for i in 96 97 98 99 00
  do
   rm $i.log $i.txt
  done
In C++ this is much more complex:
  #include <stdio.h>
  #include <stdlib.h>

  main()
  {
   char buf [ 30 ];

   for ( int i=96; i<=99; i++ )
   {
    sprintf ( buf, "rm %d.log %d.txt", i, i );
    system ( buf );
   }

   system ( "rm 00.log 00.txt" );
  }

And if you want to get directory listings Shell is much easier.
Q. How would you code the following Shell script in C++?
  for i in */*doc */*xls
  do
   cp $i $HOME/backups/$i
  done
Access to environment variables is usually a bit more awkward in the HLL:
  #include <stdlib.h>

  char *homestring = getenv ( "HOME" );



Arithmetic in Shell

Complex data structures do not exist in Shell.
But arithmetic is possible.



Arithmetic in bash

#!/usr/bin/bash

for (( i=1 ; i <= 10 ; i++ ))
do
 echo $i
done

j=5		 
echo $j
(( j++ ))
echo $j
(( j = $j + 1 ))
echo $j




Arithmetic in ksh

ksh (Korn shell) also has data types.
#!/usr/bin/ksh

integer i

i=1
echo $i
i=i+10
echo $i
i=i-4
echo $i
i=i*4
echo $i
i=i/2
echo $i




Other ways of doing arithmetic in Shell

In Shell you have TAG=VALUE pairs of text strings.
So you can set simple flags:
 flag=0

 if condition
 then
  flag=1
 fi

You can test if equality and inequality conditions are true.
For instance, test if the argument is less than 50:
 if test $1 -lt 50
Using the "expr" command, you can do arithmetic:

# x = $1 + $2

x=`expr $1 + $2`



Example

We can write the following in Shell:

flag=0
echo $flag

while test $flag -lt 30
do
 flag=`expr $flag + 1`
 echo $flag
done

which is equivalent to the following in C++:
int flag = 0;
cout << flag << "\n";

while ( flag < 30 )
{
 flag++;
 cout << flag << "\n";
}

The C++ program will run a lot faster of course!

So despite the fact that the Shell environment variables here are only text strings, and have no types, we can use other programs (test, expr) that interpret their text string arguments in certain ways, and so we can use them as numeric types after all.

But this is only the start of it of course. In C++, you also have large data types like arrays, structs, object-oriented classes with inheritance, class libraries of useful functions, and all the other equipment of a HLL. In Shell, you need to construct your functionality by piping together lots of tools at the command-line. This can get very slow and cumbersome for large, complex programs.

For any application with a GUI or threads you would turn to a HLL.


Question - Why does the C++ program run a lot faster?

Hint:

$ which expr
/bin/expr

$ ls -l /bin/expr
-r-xr-xr-x   1 bin      bin        20988 May  3  1996 /bin/expr
  flag++;  
= say 3 machine instructions (what 3?)
30 times this = 90 machine instructions.

  flag=`expr $flag + 1`  
= say 300 machine instructions (why?)
30 times this = 9000 machine instructions.



Conclusion

I tend to write my utilities in Shell if possible. For the more complex utilities, I move up to C++. For the simpler utilities I try to express them as aliases (see below).

Often, I use both. I surround a C++ utility with a small Shell wrapper that prepares the filenames and environment variables, calls the C++ program, and then possibly does some processing of the output.

In my CGI scripts, I surround Shell utilities with C++ input pre-processing wrappers.



Perl

Perl is an interpreted language designed to give much of the functionality of a language like C++ in the interpreted world of Shell - with direct access to the command-line.

Perl is popular in particular for CGI scripts (but by no means necessary).



aliases

For short one-line "scripts" or command-lines, instead of a shell script it is more efficient to use aliases in your .cshrc / .bashrc file.




Summary - What language should I use?

I want to customise my system, and automate many tasks.
Like any programmer, I am always starting to write programs. How should I approach writing small custom utilities?

  1. Very simple customisation - Check out program preferences or command-line arguments.
  2. 1-liner utilities - aliases
  3. Command-line utilities with some logic - Shell
  4. Complex command-line utilities - Perl
  5. Small applications doing lots of calculations - C++ (or HLL of your choice)
  6. Complex applications - Before investing a load of time in writing it yourself, maybe look online for freeware, shareware, or even a full commercial product.





Windows command line

The DOS command-line on Microsoft Windows also has a scripting language. You put your commands in a "batch file" with a name like PROG.BAT, and then to run it type PROG.

Some things you can do:


  1. There are pipes:
     dir | find "string" | sort
    
  2. Redirection:
     dir > file
    
  3. Command-line arguments, and string compare:
      if '%1'=='' echo No arg.
    
  4. Some equivalents of UNIX utilities (but rather few, and with usually a lot less functionality):
    grep - FIND
    sort - SORT
    
  5. FOR loops:
      for %%i in (*.html) do call secondprog %%i
    
  6. Environment variables:
    
    set myvar=string
    echo myvar is %myvar%  
    
      echo path is %path%
    
      copy %1 %homepath%\backup
    
    
  7. multiple statements in block:
    
    @echo off
    rem the above line prevents the script echoing back the commands
    rem is a comment
    
    for %%i in (*.*) do (
      echo %%i
      dir %%i
    )
    
    
  8. IF and ELSE:
    
    IF EXIST "C:\Program Files\Mozilla Firefox" (
      echo Firefox exists
    
    ) ELSE (
      echo Firefox missing
    )
    
    
  9. CALL of another batch file


But the scripting language is a bit more primitive than Shell, and the standard utilities are fewer, and have less options, than on UNIX/Linux systems.
People who like command lines tend to migrate to UNIX/Linux.




Similar to UNIX, on DOS/Windows you may or may not make use of this programmable command-line (you can survive without ever going near it). If you use it you might adopt a similar policy - write your utilities if possible as batch files, and only turn to a HLL for the more complex utilities.

For example:

  1. Earlier in my career, I spent most of my time on DOS/Windows systems, and wrote all my utilities in a combination of DOS BAT files and Pascal EXE's.
  2. For the last number of years, I have spent most of my time on UNIX systems, and have a similar system, with all my utilities in a combination of Shell scripts and C++ binaries.
You may prefer to use a combination of Perl scripts and Java programs (respectively). The principle is the same.





Feeds      HumphrysFamilyTree.com

Bookmark and Share           On Internet since 1987.