If what you want is a list of executable files, find is plenty:
IFS=':'
find $PATH -type f '(' -perm -u+x -o -perm -g+x -o -perm -o+x ')'
This will list the full path of every executable in your $PATH. The IFS=':' ensures that $PATH is split at colons (:), the separator for that variable.
If you don't want the full path, but just the executable names, you might do
IFS=':'
find $PATH -type f '(' -perm -u+x -o -perm -g+x -o -perm -o+x ')' -exec basename {} \; | sort
If your find is GNU-compatible, the condition simplifies quite a bit:
IFS=':'
find $PATH -type f -executable -exec basename {} \; | sort
As @StephenHarris points out, there is a bit of an issue with this: if there are subdirectories of your $PATH, files in those subdirectories might be reported even though $PATH cannot reach them. To get around this, you would actually need a find with more options than POSIX requires. A GNU-compatible can get around this with:
IFS=':'
find $PATH -maxdepth 1 -type f -executable -exec basename {} \; | sort
The -maxdepth 1 tells find not to enter any of these subdirectories.
PATH=:/bin::/usr/bin:which lists the current directory,., three times implicitly — before the first colon, between the consecutive colons, and after the trailing colon. So far, the answers would not interpolate the current directory when expanding PATH. It's up to you whether you regard that as a problem or not. Fixing it is decidedly non-trivial.