sh: update dir_colors
[mina86-dot-files.git] / bin / pcd.sh
blobfb201282f4ead111f770e1d8b4d118ca706ae6dd
1 # shellcheck shell=sh disable=SC2164
3 # Powerful cd, a cd command replacement
4 # Copyright 2024 Michał Nazarewicz <mina86@mina86.com>
6 # Permission is hereby granted, free of charge, to any person obtaining a copy
7 # of this software and associated documentation files (the “Software”), to deal
8 # in the Software without restriction, including without limitation the rights
9 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 # copies of the Software, and to permit persons to whom the Software is
11 # furnished to do so, subject to the following conditions:
13 # The above copyright notice and this permission notice shall be included in all
14 # copies or substantial portions of the Software.
16 # THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 # SOFTWARE.
25 # A ‘cd’ command replacement with additional features. To use source this file
26 # and proceed using ‘cd’ as you’ve been doing before. To install permanently,
27 # add sourcing of the file to ~/.bashrc, ~/.shellrc or equivalent for your
28 # choice of shell.
30 # See https://mina86.com/2024/powerful-cd/ for more detailed description.
33 cd() {
34 case $#:$1 in
35 0:)
36 command cd
37 return
40 1:--help)
41 cat <<EOF
42 Usage:
43 cd Move to home directory.
44 cd -P Resolve all symbolic links in \$PWD.
45 cd [-L | -P | --] <target> Move to given <target>.
46 cd [-L | -P | --] <target> <cmd>... Run <cmd> in the given <target>.
48 <target> can be:
49 - Move to directory stored in \$OLDPWD.
50 .../<path> Move to a sibling/cusing directory <path>; this will iterate
51 up the directories until <path> is located.
52 <file> Move to directory containing the file.
53 <dir> Move to given directory.
54 EOF
55 return
58 1:-[LP])
59 set -- "$1" "${PWD}"
61 1:*)
62 set -- -L "$1"
63 esac
65 case $1 in
66 --) shift; set -- -L "$@"; ;;
67 -[LP]) :; ;;
68 *) set -- -L "$@"
69 esac
71 if [ $# -eq 2 ]; then
72 _cd_do "$@"
73 else
74 ( _cd_do "$1" "$2" && shift 2 && exec "$@" )
79 _cd_do() {
80 case $2 in
84 .../*)
85 set -- "$1" "$2" .. "${2#*/}" "$(stat -Lc%d:%i /)"
86 while
87 if [ -e "$3/$4" ]; then
88 set -- "$1" "$3/$4"
89 if ! [ -d "$2" ]; then
90 set -- "$1" "$(dirname "$2")"
92 false
93 else
94 test "$5" != "$(stat -Lc%d:%i "$3")"
97 set -- "$1" "$2" "../$3" "$4" "$5"
98 done
101 if [ -e "$2" ] && ! [ -d "$2" ]; then
102 set -- "$1" "$(dirname "$2")"
104 esac
105 command cd "$1" -- "$2"