sfm

Simple File Manager
git clone git://git.emmett1.my/sfm.git
Log | Files | Refs | LICENSE

commit 12c85202f92282e7c92c3295c01f494bcbe13a95
parent 7f41df91f18cb32a34d4cff2746e4344d8f7830d
Author: emmett1 <emmett1.2miligrams@protonmail.com>
Date:   Mon, 16 Mar 2026 00:11:24 +0800

fix double slash at directory name

Diffstat:
Msfm | 34++++++++++++++++++++++------------
1 file changed, 22 insertions(+), 12 deletions(-)

diff --git a/sfm b/sfm @@ -61,7 +61,7 @@ term_rows() { tput_cmd lines || echo 24; } term_cols() { tput_cmd cols || echo 80; } # --- state --- -CWD="$PWD" +CWD="$PWD"; CWD=$(cd "$CWD" 2>/dev/null && pwd) || CWD="/" SEL=0 OFFSET=0 PREV_SEL=0 @@ -82,6 +82,16 @@ SHOW_DETAILS=0 # 1 = show size+date column TRASH_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/sfm-trash" mkdir -p "$TRASH_DIR" PREV_CWD="" # last visited directory, for jumping back + +# normalise CWD: resolve to absolute canonical path, no double slashes +norm_cwd() { + CWD=$(cd "$CWD" 2>/dev/null && pwd) || CWD="/" + # squeeze any double slashes (some systems return // for //<path>) + CWD=$(printf '%s' "$CWD" | tr -s '/') +} + +# safely join CWD with a name, avoiding double slash at root +joinpath() { [ "$CWD" = "/" ] && printf '/%s' "$1" || printf '%s/%s' "$CWD" "$1"; } BOOKMARK_FILE="${XDG_CONFIG_HOME:-$HOME/.config}/sfm/bookmarks" mkdir -p "$(dirname "$BOOKMARK_FILE")" [ -f "$BOOKMARK_FILE" ] || touch "$BOOKMARK_FILE" @@ -873,7 +883,7 @@ do_go_back() { SELECTED="" PREV_CWD="$CWD" LAST_CHILD="${CWD##*/}/" # name of current dir with trailing slash - CWD=$(dirname "$CWD") + CWD=$(cd "$(dirname "$CWD")" && pwd) SEL=0; OFFSET=0; PREV_SEL=0; PREV_OFFSET=0 load_entries # restore selection to the directory we just came from @@ -890,20 +900,20 @@ do_open() { */) FILTER="" SELECTED="" - _target="${CWD}/${entry%/}" + _target=$(joinpath "${entry%/}") if [ ! -x "$_target" ] || [ ! -r "$_target" ]; then INFO_MSG="permission denied: ${entry%/}" NEED_FULL_REDRAW=1 return fi PREV_CWD="$CWD" - CWD=$(cd "$_target" && pwd) + CWD=$(cd "$_target" && pwd); norm_cwd SEL=0; OFFSET=0; PREV_SEL=0; PREV_OFFSET=0 load_entries ;; *@) _name="${entry%@}" - _target="${CWD}/${_name}" + _target=$(joinpath "$_name") if [ -d "$_target" ]; then if [ ! -x "$_target" ] || [ ! -r "$_target" ]; then INFO_MSG="permission denied: ${_name}" @@ -912,7 +922,7 @@ do_open() { fi FILTER=""; SELECTED="" PREV_CWD="$CWD" - CWD=$(cd "$_target" && pwd) + CWD=$(cd "$_target" && pwd); norm_cwd SEL=0; OFFSET=0; PREV_SEL=0; PREV_OFFSET=0 load_entries else @@ -1059,7 +1069,7 @@ do_shell() { printf '%s(type "exit" to return to fm)%s\n' "${YELLOW}" "${RESET}" ${SHELL:-sh} # restore CWD in case user cd'd around - CWD="${PWD}" + CWD="${PWD}"; norm_cwd setup_term; hide_cursor NEED_FULL_REDRAW=1 } @@ -1095,7 +1105,7 @@ do_trash() { do_open_trash() { PREV_CWD="$CWD" FILTER=""; SELECTED="" - CWD="$TRASH_DIR" + CWD="$TRASH_DIR"; norm_cwd SEL=0; OFFSET=0; PREV_SEL=0; PREV_OFFSET=0 load_entries } @@ -1124,7 +1134,7 @@ do_copy_path() { do_jump_back() { [ -z "$PREV_CWD" ] && { INFO_MSG="no previous directory"; NEED_FULL_REDRAW=1; return; } _tmp="$CWD" - CWD="$PREV_CWD" + CWD="$PREV_CWD"; norm_cwd PREV_CWD="$_tmp" FILTER=""; SELECTED="" SEL=0; OFFSET=0; PREV_SEL=0; PREV_OFFSET=0 @@ -1199,7 +1209,7 @@ do_bookmark_jump() { '[C') # right — open _chosen=$(awk -v n="$_bsel" 'NR==n&&NF{print;exit}' "$BOOKMARK_FILE") if [ -n "$_chosen" ] && [ -d "$_chosen" ]; then - PREV_CWD="$CWD"; CWD="$_chosen" + PREV_CWD="$CWD"; CWD="$_chosen"; norm_cwd FILTER=""; SELECTED="" SEL=0; OFFSET=0; PREV_SEL=0; PREV_OFFSET=0 load_entries @@ -1215,7 +1225,7 @@ do_bookmark_jump() { l) _chosen=$(awk -v n="$_bsel" 'NR==n&&NF{print;exit}' "$BOOKMARK_FILE") if [ -n "$_chosen" ] && [ -d "$_chosen" ]; then - PREV_CWD="$CWD"; CWD="$_chosen" + PREV_CWD="$CWD"; CWD="$_chosen"; norm_cwd FILTER=""; SELECTED="" SEL=0; OFFSET=0; PREV_SEL=0; PREV_OFFSET=0 load_entries @@ -1373,7 +1383,7 @@ while true; do u) do_trash ;; U) do_open_trash ;; '`') do_jump_back ;; - '~') PREV_CWD="$CWD"; CWD="$HOME"; FILTER=""; SELECTED="" + '~') PREV_CWD="$CWD"; CWD=$(cd "$HOME" && pwd); FILTER=""; SELECTED="" SEL=0; OFFSET=0; PREV_SEL=0; PREV_OFFSET=0; load_entries ;; c) do_copy_path ;; "$(printf '\033')") do_clear_filter ;;