💾 Archived View for thrig.me › blog › 2023 › 11 › 19 › weird-shell-functions.gmi captured on 2024-08-18 at 18:10:03. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2023-12-28)
-=-=-=-=-=-=-
function cmdindir { local cmd=$1 local dir=$2 shift 2 # NOTE $cmd gets a split and a glob expansion /bin/mkdir -p -- "$dir" && $cmd -- "$@" "$dir" \ && builtin cd -- "$dir" \ && pwd } function cpto { if [[ $# -lt 2 ]]; then print >&2 'Usage: cpto dir file [..]'; false else cmdindir cp "$@" fi } function mvto { if [[ $# -lt 2 ]]; then print >&2 'Usage: mvto dir file [..]'; false else cmdindir mv "$@" fi }
These functions provide wrappers for "cp" and "mv" that create the destination directory, copy (or move) the given files, and change the shell into the directory. That is,
$ mvto foo/bar/zot baz
is much the same as:
$ mkdir -p foo/bar/zot $ mv baz foo/bar/zot $ cd foo/bar/zot
The "pwd" is to let you know where you are, as usually the working directory does not change as a result of a random command, so it may help to have a reminder. PS1='$ ' so I generally do not know where the shell is; that's what pwd(1) or a wrapper program that gets the current directory into the clipboard is for.
#!/bin/sh # pwd2clip - get working directory into clipboard and print it out pwd | copycat
I've seen people with the shell prompt showing all sorts of information ignore that information and make an error, so why not minimize the shell prompt? Something to try out, and it makes copying and pasting shell examples easier.
A fancy shell like ZSH could pop the directory off the end, which would make the argument order behave more like it does for cp and mv. Traditional shells only have "shift" compared to the full "shift", "pop", "unshift", and "push" functions in Perl. Fancy shells also let you use various cryptic shortcuts to refer to previous arguments, which may also help cut down on repetitions of the same long path.
function cd { if [[ -z "$1" ]]; then builtin cd elif [[ -d "$1" ]]; then builtin cd -- "$1" elif [[ -a "$1" ]]; then builtin cd -- "$(dirname -- "$1")" else builtin cd "$@" fi }
The main benefit here is to chdir to a file: given "cd /etc/passwd" the working directory becomes "/etc". This lets you paste a file path to cd and have it do something appropriate. Others might want cd to fail with an error, but then you would need to modify a filepath to get to the directory of that file. This function could instead be called "fcd" to avoid changing how "cd" behaves, but then you'd need to remember to use fcd when a filepath is involved.
More things could be done with this function, e.g. to make it aware of version control branches, or however much rope you want to rig up the footguns with.
Another way to solve the above problem would be with a subshell: some commands are run, preparation work is done, and then a new directory is spawned in a particular directory. This avoids the need to perform the chdir in the parent shell process, though can accumulate subshells.
Or, one might have some sort of communication means so that the parent shell is informed that it should chdir somewhere as a result of a command. But that would be a bit more complicated, and might get into security issues and unexpected bugs as random child processes do random things with the working directory of some parent process.
tags #ksh #unix