-->

Previous | Table of Contents | Next

Page 362

There is no need to specify filenames to xargs because it reads these from the standard input, so the xargs command will be


xargs grep -l foo

To get a list of files for xargs to give to grep, use find to list the files in /usr/src/linux that end in .c:


find /usr/src/linux -name "*.c"

Then attach the standard output of find to the standard input of xargs with a pipe:


find /usr/src/linux -name "*.c" | xargs grep -l foo

Finally, tack on a wc -l to get a count and you have


find /usr/src/linux -name "*.c" | xargs grep -l foo | wc -l

On my system this took about 29 seconds, which is considerably faster. The difference becomes even greater when more complex commands are run and the list of files is longer.

You need to be careful about filenames that contain spaces in them. Many people believe that spaces are not valid characters in UNIX filenames, but they are, and handling them correctly is becoming an issue of greater importance because today many machines are able to mount and read disks from systems that frequently use spaces in filenames.

I routinely mount Mac HFS disks (Zip, floppy, hard disk) and many files on these disks have spaces in their filenames. This will confuse xargs because it uses the newline character (\n) and the space character as filename delimiters. The GNU version of xargs provides a pretty good workaround for this problem with the --null and -0 options, which tell xargs to use the null character (\0 or \000) as the delimiter. In order to generate filenames that end in null, find can be given the -print0 option instead of -print.

As an illustration, here is an ls of my Mac's Zip Tools disk:


./              .resource/      Desktop DB*     System Folder/ ../

.rootinfo       Desktop DF*     Utilities/ .finderinfo/    Applications/   Icon:0d*

Notice that the Desktop DB and the Desktop DF files have spaces in them, as does the System Folder directory. If I wanted to run through this Zip disk and remove all files that end in prefs copy, I would normally try


find /mnt/zip -name "*prefs copy" -print | xargs rm

However, this won't work because I have a filename with spaces, but if I add -print0, I can do this with no problems:


find /mnt/zip -name "*prefs copy" -print0 | xargs rm

Two other options that are useful for xargs are the -p option, which makes xargs interactive, and the -n args option, which makes xargs run the specified command with only args number of arguments.

Page 363

Some people wonder why the -p option. The reason is that xargs runs the specified command on the filenames from its standard input, so interactive commands like cp -i, mv -i, and rm -i don't work right. The -p option solves that problem. In the preceding example, the -p option would have made the command safe because I could answer yes or no to each file. So the real command I typed was the following:


find /mnt/zip -name "*prefs copy" -print0 | xargs -p rm

Many users frequently ask why xargs should be used when shell command substitution archives the same results. The real drawback with commands such as


grep -l foo `find /usr/src/linux -name "*.c"`

is that if the set of files returned by find is longer than the system's command-line length limit, the command will fail. The xargs approach gets around this problem because xargs runs the command as many times as is required, instead of just once.

Shell Utilities

The GNU shell utilities are a package of small shell programming utilities. The following programs are included in the package:

basename printenv
chroot printf
date pwd
dirname seq
echo sleep
env stty
expr su
factor tee
false test
groups true
hostname tty
id uname
logname users
nice who
nohup whoami
pathchk yes

Who's Who in GNU

One of the first things many people do when they log on to a new machine is to see who else is logged on. The GNU shell utilities provide the commands who and users to give

Page 364

information about which users are currently logged on and what they are doing. The users command just prints out a list of names of people who are logged on. The who command is much more sophisticated.

In addition to giving information about who is logged on, who makes it possible to find out how long people have been idle, when they logged on, and if they are allowing other people to talk. Some of the options that who recognizes are as follows:

-H or --heading Prints a heading
-T, -w, or--mesg Adds user message status as +, -, or ?
-i, -u, or --idle Adds user idle time as HOURS:MINUTES, . (less than a minute), or old (greater than a day)

One of the useful features of who over users is that because who outputs one user entry per line, it can be used with commands like grep or sed to process and format its output with ease.

The id Commands

The next set of frequently used commands are the id commands.

Knowing your own uid and gid and having the ability to determine other users' uids and gids are very handy skills.

Almost all users know about the commands whoami and groups, but many have never heard of id, which encompasses their functionality and adds the ability to determine user information about other people on the system.

By default, the id command prints out all the identification information about the current user. When I run id on my system, I get (as myself)


uid=500(ranga) gid=100(users) groups=100(users)

But, I can also run id on my brother's login name:


id vathsa

and I get


uid=501(vathsa) gid=100(users) groups=500(vathsa)

I could have determined all the preceding information by looking in /etc/passwd, but id is a much easier way of accomplishing the task.

In addition, the output of id can be tailored using the following options:

-g or --group Prints only the group ID
-G or --groups Prints only the supplementary groups
-n or --name Prints a name instead of a number

Previous | Table of Contents | Next