DOC HOME SITE MAP MAN PAGES GNU INFO SEARCH PRINT BOOK
 
Automating frequent tasks

Writing a short shell script: an example

The SCO OpenServer system identifies and manages files and directories using the concept of the inode (index node). Each inode has a unique numerical identifier and stores such information as the file type, its size, where it is physically stored on disk, the date and time of the most recent access and modification, and so on. The filename is simply an aid for the user, and each file can have more than one filename. Each pathname to a file is known as a link. (For information on linking files, see ``Creating links to files and directories''.)

When a file has several links, you must remove all of them before you can delete the file itself. Therefore, it is desirable to be able to trace all the links to a given file. You can do this using the inode to search for all the filenames that have that inode number.

To list the inode of a file, use the following command:

ls -i

This lists each inode in the current directory, followed by the filename associated with it:

   $ ls -i
    1125 0.order.number
    2852 0.parts.index
    5315 0.order.index
     770 00.partno.err
    4225 00.partno.out
   $
For example, the inode number of 0.parts.index is 2852.

To find the inode of a given file, you could type something like the following:

ls -i 0.parts.index | awk '{print $1}'

The first part of the pipeline lists the inode of the file called 0.parts.index. The output from this command is fed into awk, which prints the first field, that is, the inode number:

   2852
However, printing the inode number of a file and using the inode number to do something useful are not the same. We need some way to capture the output of a command.

This can be done using a variable, using the backquote notation (recognized in the Bourne and Korn shells):

variable=`command`

command is executed, then its output is stored in variable. For example:

   $ myinum=`ls -i 0.parts.index | awk '{print $1}'`
   $ echo $myinum
   2852
   $
The C shell recognizes the corresponding notation:

set variable `command`

Having obtained the inode number and stored it in an environment variable, we can then use it in a find command. For example:

find / -inum $myinum -print

The find option -inum tells find to look for files matching the inode number stored in the variable myinum. The option -print tells find to print the names of any files it matches. (This command also outputs a list of all the directories it cannot access as it reaches them.)

Now we can write a shell script that, given a filename, searches for all links that point to the same file:

   myinum=`ls -i $1 | awk '{ print $1 }'`
   find / -inum $myinum -print 2> /dev/null
In summary, the first line assigns the inode of the specified file (here represented by the positional parameter $1) to the variable myinum. Note that the second ``$1'' notation in this line is internal to awk, and refers to the first field of the output piped from ls -i, and not back to the specified filename.

The second line of the script invokes find, telling it to start at the root directory (/) and search through all the mounted filesystems for files matching the inode number found in the variable myinum, and print their names.

Note that an inode number is only unique within a given filesystem. It is possible for two files with the same inode number to exist on different filesystems, and not be linked together. It is therefore worth checking the output to make sure that all the files output by this script reside on the same filesystem.

find prints a message to the standard error if it cannot look inside a directory. We do not want to see these error messages, so the standard error output from find (output stream 2) is redirected to the device /dev/null; an output stream sent to this device is silently ignored. Consequently, the error messages are discarded and a clear, uncluttered output is produced. (Non-spurious errors are also indiscriminately discarded. However, in this example all errors are probably spurious, so discarding all messages is acceptable.)


Next topic: Passing arguments to a shell script
Previous topic: Running a script under any shell

© 2005 The SCO Group, Inc. All rights reserved.
SCO OpenServer Release 6.0.0 -- 03 June 2005