Recently I've found myself in need to reinstall the linux system, to change MBR partition to GPT. Before I do that though I need to find files I've had configured for my system, and I could use a bunch of applications for that, none of them though offer a holistic approach. So how about a diff walker (similiar to disk-usage walkers)? I could set up a directory with bare system and investigate what I've added manually. However options for that are limited, but it was easy to implement a simple version of it myself. With use of lf and recently added feature: on-load.
- Basically we generate a cache with differences between two directories.
- Then we use on-load to set custom display information in the view.
- To start the process we will use an lf command.
- We change the previewer to diff previewer while in diff mode
This will allow us to pull the cached differences and investigate what's been changed, however the use applications are many.
user@machine:~/r/i3switch/.git
.git 119% - branches 100% -
.github 100% - filter-repo 100% -
cpp 100% - git-cliff-core 100% -
docs 100% - hooks 0% -
python 100% - info 50% -
rust 100% - logs 136% -
scripts 100% - modules 23% -
.clang-format 0% 32B objects 100% -
.gitignore 120% 213B refs 122% -
Makefile 100% 799B COMMIT_EDITMSG 200% 46B
README.md 188% 3.5K config 145% 279B
tags 100% 3.1M description 0% 73B
fast_import_crash_2704499 100% 735B
fast_import_crash_3105971 100% 465B
FETCH_HEAD 400% 87B
HEAD 200% 33B
index 100% 7.8K
ORIG_HEAD 200% 41B
packed-refs 121% 854B
drwxr-xr-x 11 user user 4.0K Thu Jul 3 13:09:24 2025 1 1/12
The scripts are attached. Caching script takes base directory path and reference
directory path, generates cache in ~/.cache/lf/diff_cache.txt.
We will put it in ~/.config/lf/gen_diff_cache.sh.
Previewer script will display the preview of the diff between the files, so we can
glance at what has been changes.
We will put it in the same directory ~/.config/lf/diff_previewer
Now we add a function that will start the caching process to lfrc (typically ~/.config/lf/lfrc)
and enter diff mode, replacing default previewer and a function that will stop the diff mode
restoring previewer.
set user_diff_mode false
set user_diff_base_path ""
set user_diff_ref_path ""
set user_diff_cache_path "$HOME/.cache/lf/diff_cache.txt"
set user_diff_previewer ~/.config/lf/diff_previewer
cmd start_diff ${{
set -f
base_path="${f%/*}"
ref_path="$1"
if [ $# -ne 1 ]; then
printf "Specify reference dir: "
read ref_path
fi
[ -z "$ref_path" ] && ref_path="$(pwd)"
ref_path="$(realpath "$ref_path")"
[ -d "$ref_path" ] || return 1
echo "You're about to start a diff session with:"
echo "base path: $base_path"
echo "reference path: $ref_path"
printf "Generating cache will take a while, continue? [y/n]" "$ref_path" "$base_path"
read ans
[ "$ans" != "y" ] && return 1
cmds="set user_diff_mode true; "
cmds+="set user_diff_base_path '$base_path'; "
cmds+="set user_diff_ref_path '$ref_path'; "
cmds+="set user_diff_previewer '$lf_previewer'; "
cmds+="set previewer '$lf_user_diff_previewer'; "
cmds+="set hidden; reload"
lf -remote "send $id :$cmds"
$HOME/.config/lf/gen_diff_cache.sh "$base_path" "$ref_path"
}}
cmd stop_diff ${{
set -f
cmds="set user_diff_mode false; "
cmds+="set user_diff_base_path ''; "
cmds+="set user_diff_ref_path ''; "
cmds+="set user_diff_previewer '$lf_previewer'; "
cmds+="set previewer '$lf_user_diff_previewer'; "
cmds+="reload"
lf -remote "send $id :$cmds"
}}
The start_diff function will take the current directory as a base directory and take an argument or ask the user about the reference directory. Then it will update lf user options to enable diff mode and to store the reference path we provided. It will also unhide files to make sure we don't miss anything, and trigger reload so on-load will reload the custom fields.
Finally when loading the directory, we will search the files in the diff cache and send the custom data to lf so it can display it in the view.
But before this works, make sure You have custom in the info option, eg:
set info custom:size # adds custom info and file size to the view
Here's the hook that we use:
cmd on-load &{{
if [ "$lf_user_diff_mode" = true ]; then
if ! [[ "$1" = "$lf_user_diff_base_path"* ]]; then
return 0 # let's not waste time if the base path is not correct
fi
diff_cache_path=$( envsubst <<<"$lf_user_diff_cache_path" )
cmds=""
for file in "$@"; do
diff_line="$(grep "^$file " "$diff_cache_path")"
[ -n "$diff_line" ] || continue
percent="${diff_line#* }"
if [ "$percent" -eq "0" ]; then
percent="\033[1;32m$percent%\033[0m" # print in green
elif [ "$percent" -le "50" ]; then
percent="\033[1;33m$percent%\033[0m" # print in yellow
else
percent="\033[1;31m$percent%\033[0m" # print in red
fi
cmds+="addcustominfo '$file' \"$percent\";"
done
lf -remote "send $id :$cmds"
return 0
fi
# You can keep your on-load things below, that will not trigger in diff mode
}}
To start diff session we will use :start_diff ../ref_dir and confirm that we want to continue.
When we're done we can just input :stop_diff and we will be back to normal mode. Neat!