Qshell command language features

Learn more about commands, input and output redirection, path name expansion, parameter expansion, and command substitution.

The shell interpreter can be used for either an interactive session or for writing shell scripts. A shell script is just a text file that contains shell commands. The Qshell command language is identical for either interactive use or for writing scripts. Any command that you run from an interactive command line can be put in a shell script and it runs the same way. The Qshell command language is interpreted so a shell script is read and interpreted each time it is run.

Commands

A simple command is the name of a utility that you want to run. If you specify a fully-qualified path name to the command, for example "/usr/bin/ls", qsh runs that command. If you specify a relative path name to the command, for example "ls", qsh searches the directories specified by the PATH variable to find it. The PATH variable is a colon delimited list of directories that tells qsh where to find commands. If the PATH variable is set to

/usr/bin:.:/QOpenSys/usr/bin

qsh first looks for the command in the "/usr/bin" directory, then in the current working directory, and finally in the "/QOpenSys/usr/bin" directory. When the PATH variable begins or ends with a colon, contains two adjacent colons or specifies a dot (.) as a directory, qsh searches in the current working directory.

By default, qsh waits for the command to complete before running the next command. When the command is completed, it sets an exit status that describes the result of the command. An exit status of zero means that the command was successful. An exit status that is greater than zero means that the command was unsuccessful. Typically, the exit status is one when a command fails. Although, qsh sets the exit status to 126 when the command was found but could not be run and sets the exit status to 127 when the command was not found.

The compound commands include the if-then-else conditional, [[...]] conditional, case conditional, select conditional, while loop, until loop, for loop, and functions. These commands provide the features you would expect in a high-level programming language and allow you to write complex shell scripts.

A pipeline allows you to chain several commands together so the output from one command is the input to the next command. For example, in the pipeline

ls | grep ^apple

the output from the ls utility becomes the input to the grep utility. The ls utility lists the contents of a directory and the grep utility searches for matches to a pattern. The final output of the above pipeline is a list of the files in the current directory that begin with "apple".

You can chain more than two commands in a pipeline. This is a very powerful feature of qsh that allows you to combine several commands together to accomplish a complex task.

There are two other types of lists that are like pipelines. An "and" list stops when the first command in the list has non-zero exit status. An "or" list stops when the first command in the list has a zero exit status.

An asynchronous list runs a command in the background. For example, the command

mypgm &

allows you to start mypgm and then run other commands before mypgm completes. If you have a long running command, an asynchronous list allows you to start the command and not wait for the command to complete.

Input and output redirection

Input and output redirections allow you to change where input for a command comes from and where output for the command goes to. For Qshell commands, input and output work on descriptors. A descriptor can be opened to either an object in the Integrated File System or to a TCP/IP socket. Input comes from descriptor 0 or standard input, regular output goes to descriptor 1 or standard output, and error output goes to descriptor 2 or standard error.

You can change where input comes from by redirecting standard input. For example, in the command

grep orange <fruits.list

when the grep utility reads from standard input it receives the contents of the file fruits.list.

You can change where output goes to by redirecting standard output. For example, in the command

grep apple fruits.list >apple.list

when the grep utility writes the results to standard output, the results are written to the file apple.list.

You can also send standard output and standard error to the same file. For example, in the command

grep apple fruits.list >apple.list 2>&1

standard output (descriptor 1) is written to the file apple.list and standard error (descriptor 2) is redirected to the same place as descriptor 1.

While most of the time redirections are only used to control standard input, standard output, and standard error, you can control the descriptors from 0 to 9 using redirections.

Path name expansions

A path name expansion substitutes a pattern for all of the files that match the pattern. A shell pattern uses:
  • A * to match any string of characters. For example, in the command
    ls *.java
    qsh expands *.java to all of the files that end with .java in the current working directory.
  • A ? to match any single character. For example, in the command
    ls *.?
    qsh expands *.? to all of the files that have a single character extension.
  • A [ ] for a character class. With a character class, qsh matches a set or range of characters. For example, in the command
    ls *.[ch]
    qsh expands *.[ch] to all of the files that end in either .c or .h in the current working directory. You can also specify a range of characters. For example, in the command
    ls *.jav[a-c]
    qsh expands *.jav[a-c] to all of the files that end in .java, .javb, or .javc.

Parameter expansions

A parameter expansion substitutes the value of a variable. In the simplest form

$myvar 

qsh substitutes the value of the variable myvar.

There are modifiers to use default or alternate values or to indicate an error if the variable is unset or null. For example, in the parameter expansion

${counter:=0}

qsh sets the default value of the variable counter to zero if the variable is unset or null. If the variable counter was already set, the value is not changed and the current value is substituted.

There are also modifiers to remove small or large prefix or suffix patterns. The patterns are the same as the ones used for path name expansions. There are four pattern modifiers:

For example, if the variable pathname is set to "/fruits/apples/grannysmith", then in the parameter expansion

${pathname%/*}

qsh removes the smallest right pattern that matches "/*" and "/fruits/apples" is substituted.

Command substitutions

A command substitution allows the output of a command to be substituted in place of the command name. For example, in the command substitution

$(grep apple fruit.list)

qsh substitutes the output of the grep command. This is an easy way to capture the output of a command for further processing in a script.

An older form of command substitution that uses backquotes (`) is supported but should not be used because of its ambiguous quoting rules.