[Home] Zsh logo

gwhence

Zsh Wizard

Download gwhence Return to Examples
  1. #!/bin/zsh
  2. #
  3. # gwhence - generic version of builtin "whence" that works on a user-
  4. # specifiable path.
  5. #
  6. # usage:
  7. # gwhence [-a] [-m] [-s path] name . . .
  8. #
  9. # where
  10. # -a causes all matching names to be printed, not just the first
  11. # one that occurs in the path.
  12. # -m allows name(s) to be shell patterns (implies -a)
  13. # -s lets you supply a colon-separated path for gwhence to
  14. # search for name(s) (default is $PATH)
  15. #
  16. local opt elem names found all pattern ng
  17. local usage="Usage: $0:t [-am] [-s path] name . . ."
  18. # no arguments - return with zero exit status
  19. if [[ $# -eq 0 ]]
  20. then
  21. return 0
  22. fi
  23. # search path defaults to $PATH
  24. local search="$PATH"
  25. # fetch options
  26. while getopts :ams: opt
  27. do
  28. case "$opt" in
  29. 'a') all=true ;;
  30. 'm') pattern=true ;;
  31. 's') search="$OPTARG" ;;
  32. ':') [[ "$OPTARG" = 's' ]] && echo "$usage" ;;
  33. '?') echo "$usage" ; return 1 ;;
  34. esac
  35. done
  36. # put options behind us
  37. shift $[ $OPTIND - 1 ]
  38. # remember state of nullglob
  39. [[ -o nullglob ]] && ng=true
  40. setopt nullglob
  41. # if none found, must report it by nonzero exit status at end
  42. found=
  43. # for each name supplied . . .
  44. for names
  45. do
  46. # scan path, in pieces (colon is separator)
  47. for elem in ${(s/:/)=search}
  48. do
  49. # pattern matching (-m)
  50. if [[ "$pattern" = "true" ]]
  51. then
  52. # for compatibility with whence, must put next line here, not inside
  53. # following if construct
  54. found=true
  55. if [[ -n "$(eval 'echo -n $elem/'$names'')" ]]
  56. then
  57. # Must output them on separate lines
  58. eval 'echo $elem/'$names' | tr '\'' '\'' '\''\n'\'
  59. fi
  60. else
  61. if [[ -a $elem/$names ]]
  62. then
  63. echo $elem/$names
  64. # we found one - remember it
  65. found=true
  66. fi
  67. # note that "found" only applies if -m was not specified
  68. if [[ "$found" = "true" && "$all" != "true" ]]
  69. then
  70. break
  71. fi
  72. fi
  73. done
  74. done
  75. # reset nullglob status
  76. [[ "$ng" = "true" ]] || unsetopt nullglob
  77. # a name not found?
  78. if [[ "$found" != "true" ]]
  79. then
  80. return 1
  81. fi
  82. # exit safely
  83. return 0