1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- #!/usr/bin/env bash
-
- declare -r esc=$'\033'
- declare -r c_reset="${esc}[0m"
- declare -r c_red="${esc}[31m"
- declare dryrun verbose
-
- set -e
-
- err() {
- printf "${c_red}%s${c_reset}\n" "$*" >&2
- }
-
- die() {
- exit 1
- }
-
- has() {
- local verbose=0
- if [[ $1 == '-v' ]]; then
- verbose=1
- shift
- fi
- for c; do c="${c%% *}"
- if ! command -v "$c" &> /dev/null; then
- (( verbose > 0 )) && err "$c not found"
- return 1
- fi
- done
- }
-
- has -v fzf || die
-
- fzf() {
- command fzf --cycle "$@"
- }
-
- pick_files() {
- local files fzpick
- find . -maxdepth 1 2> /dev/null |
- sort -h |
- sed '1d; s|^\./||' |
- while read -r f; do
- if [[ -d "$f" ]]; then
- printf '%s/\n' "$f"
- elif [[ -L "$f" ]]; then
- printf '%s@\n' "$f"
- else
- printf '%s\n' "$f"
- fi
- done |
- fzf --multi --header='move these files' || return 1
- }
-
- pick_destination() {
- local cwd browse_dir browse_info query dirs
- cwd=$(pwd)
- while [[ "$browse_dir" != "$cwd" ]]; do
- mapfile -t browse_info < <(
- { echo '..'; find . -maxdepth 1 -type d 2> /dev/null; } |
- sed 's|^./||' |
- sort -h |
- fzf --print-query \
- --history="${HOME}/.cache/fzmv_history" \
- --header="${errors:-move files here}")
- query=${browse_info[0]}
- browse_dir=${browse_info[1]}
- files=( "${browse_info[@]:2}" )
- [[ -d "$query" ]] && browse_dir="$query"
- [[ ! -d "$browse_dir" ]] && return 1
- if [[ "$browse_dir" == '.' && $(realpath "$browse_dir") != "$cwd" ]]; then
- realpath "$browse_dir"
- break
- else
- cd "$browse_dir" || die
- continue
- fi
- done
- }
-
- while (( $# > 0 )); do
- case $1 in
- -t|--test) dryrun=true ;;
- -v|--verbose) verbose=1 ;;
- esac
- shift
- done
-
- mapfile -t files < <(pick_files)
- (( ${#files[@]} > 0 )) || exit 1
- destination=$(pick_destination) || exit 1
- ${dryrun:+echo} mv ${verbose:+-v} -t "$destination" "${files[@]}"
|