With zsh
a handy shortcut to duplicate the previous word (depending on your zle mode) is EscCtrl _ , that's the default in emacs mode. You can (re)define this yourself. e.g. just Ctrl_ which is good in a vi mode:
bindkey "^_" copy-prev-word
bindkey "^_" copy-prev-shell-word # respects shell quote/escape
With the default bash
readline bindings you can properly "edit" then execute a command line with Meta-X Meta-E. You might want to set the EDITOR
or VISUAL
variables to your preferred editor, which hopefully makes the task of duplicating a word easier.
You can nearly but not quite use the zsh copy-prev-word
in bash, but its notion of what a word is won't always make you happy (strictly alphanumeric):
bind "\C-_: copy-backward-word"
then Ctrl _ CtrlY to invoke.
Newer bash versions (since 4.0) support shell words, but not for copy, only for motion/delete, so a slight hack is:
bind "\C-_: shell-backward-kill-word"
The you can cut, then paste (yank) the word back twice with double CtrlY.
Bash also lets you bind a shell function, in which case you can do creative things by changing the variables READLINE_LINE
and READLINE_POINT
, but I don't have such a function to hand right now. Here's a toy function (bash-4.3 minimum) that either duplicates the last shell word, or if the last word appears to be a sed
command applies it to the second last shell-word and replaces itself.
function _dupl() {
[[ -z "${READLINE_LINE}" ]] && return # empty, no action
eval local -a aa=( "${READLINE_LINE}" ) 2>/dev/null # split into words
[[ ${#aa} -eq 0 ]] && return # parse problem
if [[ "${aa[-1]:0:2}" == "s/" ]]; then # sed
local _sed=$(sed -e "${aa[-1]}" <<< ${aa[-2]})
unset aa[-1] # remove last word
printf -v READLINE_LINE "%q " "${aa[@]}" # recreate line
printf -v READLINE_LINE "%s%q" "${READLINE_LINE}" "$_sed"
else
printf -v READLINE_LINE "%s %q" "${READLINE_LINE}" "${aa[-1]}"
fi
READLINE_POINT=${#READLINE_LINE} # move cursor to end
}
bind -x '"\C-_":"_dupl"'
Example:
mv "some/path/File With A Long Name.txt" s/txt/bak/
Ctrl _
is then expanded on the input line to:
mv some/path/File\ With\ A\ Long\ Name.txt some/path/File\ With\ A\ Long\ Name.bak
(you'll note that quoted words become escaped since printf %q
is used for safe expansion)
This last option is possibly over-stretching what one could consider "in a shell". if you have vim
with the netrw
script, you can simply edit the directory as a file:
vim .
- use normal search/navigation features
- use R to rename the file/directory at the cursor
See also: https://unix.stackexchange.com/questions/132235/quickest-way-to-rename-files-without-retyping-directory-path