|
|
You can of course write short command-line-driven utilities and CGI scripts in any programming language.
edit prog.cxx g++ prog.cxxThis creates a binary executable file called a.out
g++ prog.cxx -o progYou may need to: chmod +x prog
prog (args)
In a HLL, calling other programs
(and access to the command-line in general) is 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 obviously more complex than the Shell:
rm file7.txtYou 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 doneIn 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 you really want to use Shell.for i in */*doc */*xls do cp $i $HOME/backups/$i doneAccess to environment variables is also more awkward in the HLL:
#include <stdlib.h> char *homestring = getenv ( "HOME" );
On the plus side of course, is that sophisticated data structures
exist in the HLL and not in Shell.
For instance, there are no types in Shell (or at least the "vanilla" shells).
You cannot do:
int i=0; if ( condition ) i++;All you have in Shell are simple TAG=VALUE pairs of text strings. So you can only set simple flags:
flag=0 if condition then flag=1 fi
Although in fact there is a way to do arithmetic comparisons. For instance, test if the argument is less than 50:
if test $1 -lt 50And using the "expr" command, you can do arithmetic:
# x = $1 + $2 x=`expr $1 + $2`
So in fact, for the flag above, we can write the following in Shell:
flag=0 echo $flag while test $flag -lt 30 do flag=`expr $flag + 1` echo $flag donewhich 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 Shell environment variables 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, recursive function calls, object-oriented classes with inheritance, 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.
And obviously for any serious application (for instance, anything with a windowed user interface, or anything with threads) you 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/exprflag++; = say 3 machine instructions (what 3?) 30 times this = 90 machine instructions.
flag=`expr $flag + 1` |
#!/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
#!/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
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 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).
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.
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?
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:
dir | find "string" | sort
dir > file
if '%1'=='' echo No arg.
grep - FIND sort - SORT
for %%i in (*.html) do call secondprog %%i
set myvar=string echo myvar is %myvar% echo path is %path% copy %1 %homepath%\backup
@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 )
IF EXIST "C:\Program Files\Mozilla Firefox" ( echo Firefox exists ) ELSE ( echo Firefox missing )
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:
On Internet since 1987.