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]
  }
}

    
Download this file
Jeremy Holland - Code Portfolio
Contact Me