#!/usr/bin/env bash # shellcheck source=/dev/null SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH # shellcheck disable=SC2269 f="$f" # shellcheck disable=SC2269 fx="$fx" # shellcheck disable=SC2269 fs="$fs" # shellcheck disable=SC2269 id="$id" # source: https://github.com/gokcehan/lf/wiki/Tips#use-copy-on-write-when-possible # # # FIXME: Add this. The hardest part is in checking, if a file can be reflinked, as fuse and bind mount are hard to # backtrack <2023-08-29> # # This was very helpful for debugging: # log_file="$HOME/lf-reflink-log-$(date +'%Y-%m-%d_%H-%M-%S')" # [ -f "$log_file" ] || touch "$log_file" # exec 1>> $log_file 2>&1 # set -x # In theory, this may fail, # but I tested it on selection with 10k files - everything worked (bash) # FIXME: This will very likely fail on dash, when the file number > 255 <2023-08-29> set -- "$(cat ~/.local/share/lf/files)" mode="$1" shift if [ "$mode" = 'copy' ]; then # Reflink if all items of selection and the destination are on the # same mount point and it is CoW fs. # (to make sure reflink never fails in first place, so we don't have to # clean up) src_targets="$(df --output=target -- "$@" | sed '1d' | sort -u)" if [ "$(df --output=target -- "$PWD" | tail -n 1)" = \ "$(echo "$src_targets" | tail -n 1)" ] && (("$(echo "$src_targets" | wc -l)" == 1)) && [[ "$(df --output=fstype -- "$PWD" | tail -n 1)" =~ ^(btrfs|xfs|zfs)$ ]]; then echo 'selected copy and cp reflink paste' start=$(date '+%s') # Handle same names in dst # TODO parallelism, idk - but exit/return/break won't stop the loop from subshell... for i in "$@"; do name="${i##*/}" original="$name" count=0 while [ -w "$PWD/$name" ]; do count=$((count + 1)) name="$original.~$count~" done set +e cp_out="$(cp -rn --reflink=always -- "$i" "$PWD/$name" 2>&1)" set -e if [ -n "$cp_out" ]; then lf -remote "send $id echoerr $cp_out" exit 0 fi done finish=$(($(date '+%s') - start)) t='' if ((finish > 2)); then t="${finish}s" fi # Or just skip a file when names are the same. # (A LOT faster if you e.g. pasting selection of 10k files) # cp -rn --reflink=always -- "$@" . lf -remote "send clear" green=$'\u001b[32m' reset=$'\u001b[0m' lf -remote "send $id echo ${green}reflinked!${reset} $t" else echo 'selected copy and lf native paste' lf -remote "send $id paste" lf -remote "send clear" fi elif [ "$mode" = 'move' ]; then echo 'selected move and lf native paste' lf -remote "send $id paste" lf -remote "send clear" fi # # for debug # set +x lf -remote "send load" # vim: ft=sh