Differences between revisions 7 and 8
Revision 7 as of 2016-01-21 19:27:33
Size: 4490
Editor: GreyCat
Comment: expand, expand, expand
Revision 8 as of 2016-12-16 23:55:18
Size: 4474
Editor: 104
Comment:
Deletions are marked like this. Additions are marked like this.
Line 6: Line 6:
Line 10: Line 9:
Line 16: Line 14:
Line 20: Line 17:
Line 24: Line 20:
`which` is a non-standard command, though commonly available. It is useless and redundant, both in scripts and interactive shells. Some common bad usages:
Line 25: Line 22:
`which` is a non-standard command, though commonly available. It is useless and redundant, both in scripts and interactive shells. Some common bad usages:
Line 32: Line 28:
What happens here is that `which` searches for `grep` in the `PATH` environment variable, and outputs the path to the first `grep` it finds. If it doesn't find it, it might output nothing, output an error to stdout, or output an error to stderr, and it may or may not return a non-zero exit status. If you happen to have a `which` command that outputs nothing when the command is not found, the above may result in the `GREP` variable being empty, in which case `$GREP rm logfile` expands into `rm logfile`, which does something else than search for the string "rm" in logfile.  What happens here is that `which` searches for `grep` in the `PATH` environment variable, and outputs the path to the first `grep` it finds. If it doesn't find it, it might output nothing, output an error to stdout, or output an error to stderr, and it may or may not return a non-zero exit status. If you happen to have a `which` command that outputs nothing when the command is not found, the above may result in the `GREP` variable being empty, in which case `$GREP rm logfile` expands into `rm logfile`, which does something other than search for the string "rm" in logfile.
Line 42: Line 39:
Line 46: Line 42:
Line 54: Line 49:
Line 60: Line 54:
Line 64: Line 57:

This page describes some common utilities that should be avoided, and what you should use instead.

pidof

pidof is a strange program. On some systems it's a symlink to the killall5 program - part of the sysvinit package. It is used by init to send signals to all processes (e.g. to kill them during shutdown). If invoked as pidof, it returns the pid of the given program. pidof Is highly nonstandard, yet seen frequently in examples likely due to its intuitive name.

Alternatives

The pgrep utility - part of the procps suite. pgrep returns pids of processes matching the given regex, and is very preferable to grepping ps output. While also nonstandard, pgrep is widely available (if not installed by default) and the utilities are generally good quality. procps also includes a pidof implementation, so if you have a choice you should definitely install it and avoid the sysvinit version.

Process names are NOT a reliable way to work with processes! Searching by name should only be done interactively in a pinch when the need to follow a process couldn't be anticipated. Never do it in scripts or programs! See: ProcessManagement.

killall

On some systems (Linux-based ones, usually) this may try to send a signal to a bunch of processes based on their names (a dodgy practice at best -- see above). On others (Unix System V-based ones) it will try to kill every running process regardless of name. In either case, it's nonstandard.

Alternatives

Use pkill, also from procps. But see ProcessManagement for proper ways to manage processes.

which

which is a non-standard command, though commonly available. It is useless and redundant, both in scripts and interactive shells. Some common bad usages:

# Wrong
GREP=`which grep`
...
$GREP rm logfile

What happens here is that which searches for grep in the PATH environment variable, and outputs the path to the first grep it finds. If it doesn't find it, it might output nothing, output an error to stdout, or output an error to stderr, and it may or may not return a non-zero exit status. If you happen to have a which command that outputs nothing when the command is not found, the above may result in the GREP variable being empty, in which case $GREP rm logfile expands into rm logfile, which does something other than search for the string "rm" in logfile.

# Right
grep rm logfile

Guess what, bash can also search through PATH for commands, in addition to first looking for aliases, functions or builtins by that name. So the which command added nothing useful, only bugs.

The other common use of which is to check if a command exists. The shell can do this already (for example using type), and better, so why use an inferior, external command?

Alternatives

The builtins type, command and hash. See BashFAQ/081

xargs

xargs is standard and moderately useful, but it has a number of unfortunate legacy warts which makes it somewhat cumbersome and sometimes outright dangerous to use. If you have a choice, consider replacing it with a more modern alternative.

Specifically, xargs splits its input on any kind of whitespace, and parses quotes. A filename with spaces or quotes in its name will not be preserved and passed along correctly.

GNU xargs has a -0 option that suppresses those misfeatures, but only for NUL-delimited input streams (e.g. those produced by GNU find with the -print0 option). But if you're doing that, you might as well just use find ... -exec foo {} + and skip xargs altogether.

Alternatives

See UsingFind for better ways to execute a command with a whole bunch of files as arguments.

Another alternative is GNU Parallel (which ironically had some odd behaviors to explain in its earlier versions...).

expr

Pure legacy program. Has no real use in a Bash script. The Bourne shell could not do arithmetic, so you had to call this external utility to increment a loop counter. Even POSIX sh can do that much.

Alternatives

For arithmetic, use $((...)), ((...)) or let. For various string manipulations and tests, see FAQ 100 or FAQ 31.

BadUtils (last edited 2022-01-11 14:21:47 by emanuele6)