path.nawk
#!/bin/nawk -f
# ==============================================================================
# path.nawk
# ==============================================================================
#
# Usage:
# path.nawk <operation> <path> <directories>
# Example:
# setenv PATH = `path.nawk append $PATH /usr/local/bin`
# Where:
# <operation> is "prepend", "append", or "delete"
# <path> is the path to modify -- typically $PATH is passed to path.nawk, but
# $MANPATH, $LD_LIBRARY_PATH, etc. can also be modified.
# <directories> is one or more colon-separated lists of directories to
# be added to or removed from <path>
#
# path.nawk prints the modified path which can be assigned to a variable.
#
# NOTE: directories are added to the path regardless of whether they actually
# exist and are accessible.
# NOTE: prepend and append operations move directories already included in the
# path to the beginning and end (respectively) of the returned path.
#
# This file is not meant to be be called directly. Create aliases such as:
# alias appP 'if ( ! $?PATH ) setenv PATH; setenv PATH `/path/to/path.nawk append $PATH \!*`'
#
# Then type or include the following in a login script:
# appP /usr/local/bin
BEGIN {
# the operation is the first argument
operation = ARGV[1]
# the existing path is the second argument
exist_path = ARGV[2]
# split the existing path on colons into an array
num_exist_path = split(exist_path, exist_path_items, ":")
# now filter the array to remove duplicates and blanks
num_filtered_exist_path = 0
for (x = 1; x <= num_exist_path; x++) {
# skip if blank
if ( exist_path_items[x] != "" ) {
# skip if already in hash
if ( exist_path_mems[exist_path_items[x]] != 1 ) {
# add to list of items passing filter
filtered_exist_path_items[++num_filtered_exist_path] = exist_path_items[x]
# add to hash
exist_path_mems[exist_path_items[x]] = 1
}
}
}
# things to add appear in third and subsequent arguments
proposed_path_mods = ARGV[3]
# join subsequent argument with a colon to get a long colon-delimited string
for (x = 4; x < ARGC; x++) {
proposed_path_mods = proposed_path_mods ":" ARGV[x]
}
# now split the whole thing on colons to get an array of proposed mods
num_proposed_path_mods = split(proposed_path_mods, proposed_path_mods_items, ":")
num_filtered_path_mods = 0
for (x = 1; x <= num_proposed_path_mods; x++) {
# skip if blank
if ( proposed_path_mods_items[x] != "" ) {
# skip if already in hash
if ( path_mods_mems[proposed_path_mods_items[x]] != 1 ) {
# add to list of items passing filter
filtered_path_mods_items[++num_filtered_path_mods] = proposed_path_mods_items[x]
# add to hash
path_mods_mems[proposed_path_mods_items[x]] = 1
}
}
}
# the output starts with zero entries
num_new_path = 0
# if we are prepending items, add them onto the front of the new path
if ( operation == "prepend" ) {
for (x = 1; x <= num_filtered_path_mods; x++) {
new_path[++num_new_path] = filtered_path_mods_items[x]
}
}
# if we are deleting items, we neither appended nor will prepend. Items in
# filtered_exist_path_items[] are not added if they appear in path_mods_mems,
# effectively deleting them.
# loop on filtered existing path items. Add each one to the new path if and
# only if it does NOT appear as a proposed mod
for (x = 1; x <= num_filtered_exist_path; x++) {
if ( path_mods_mems[filtered_exist_path_items[x]] != 1 ) {
new_path[++num_new_path] = filtered_exist_path_items[x]
}
}
# if we are appending items, add them onto the end of the new path
if ( operation == "append" ) {
for (x = 1; x <= num_filtered_path_mods; x++) {
new_path[++num_new_path] = filtered_path_mods_items[x]
}
}
# print everything delimited by colons (use printf so no \n is printed)
printf "%s", new_path[1]
for (x = 2; x <= num_new_path; x++) {
printf ":%s", new_path[x]
}
}