Subject: bug#78493: 30.1.90; dired-listing-switches "-hail --group-directories-first" fumbles filename ending with `:'

From: Eli Zaretskii <[email-masked]>
Date: Mon, 19 May 2025 17:49:40 +0300

> Date: Mon, 19 May 2025 12:15:26 +0000
> From:  Van Ly via "Bug reports for GNU Emacs,
>  the Swiss army knife of text editors" <[email-masked]>
> 
> The contents of directory `plan9-4e/rc/bin' has filenames ending with `:'.
> 
> This is a problem when the following setting applies.
> 
>   (setopt dired-listing-switches "-hail --group-directories-first")
> 
> Before the setting is applied a line appears as follows.
> 
>   -rwxr-xr-x 1 van staff  354 Dec 25  2021 9fat:
> 
> After the setting is applied the line now looks like this.
> 
>   /u/van/src/plan9/plan9-4e/rc/bin/11291923 -rwxr-xr-x 1 van staff  354 Dec 25  2021 9fat:
> 
> I am using the `gls' gnu ls command with dired-use-ls-dired variable value being `t'.
> 
> I expect the file `9fat:' to appear like `9fs', compare A and B below.
> 
>  [A] -> https://sdf.org/~van.ly/img/emacs-30.1.90-dired-1-before-setting.webp
>  [B] -> https://sdf.org/~van.ly/img/emacs-30.1.90-dired-2-after-setting.webp
> 
> To reproduce observed bug,
> 
>   1. start, `emacs -Q'
>   2. dired, `C-x d plan9-4e/rc/bin/'
>      see: [A]
>   3. apply, `(setopt dired-listing-switches "-hail --group-directories-first")'
>   4. destroy dired buffer listing `plan9-4e/rc/bin'
>   5. dired, `C-x d plan9-4e/rc/bin/'
>      see: [B]
>   6. note the appearance on the line with filename `9fat:'

Thanks.  Please try the patch below and tell if it solves the problem.

diff --git a/lisp/dired.el b/lisp/dired.el
index 63d373a..95e9fb2 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -3721,7 +3721,13 @@ dired-build-subdir-alist
 	    ;; ange-ftp listings.
 	    (and (dired-switches-recursive-p switches)
 		 (string-match "\\`/.*:\\(/.*\\)" default-directory)
-		 (concat "\\`" (match-string 1 default-directory)))))
+		 (concat "\\`" (match-string 1 default-directory))))
+           ;; Regexp that describes the beginning of line of a
+           ;; file/directory entry (as opposed to a subdirectory
+           ;; heading), including the optional mark, inoder, and size.
+           (file-entry-beg-re (concat dired-re-maybe-mark
+                                      dired-re-inode-size
+                                      dired-re-perms)))
       (goto-char (point-min))
       (setq dired-subdir-alist nil)
       (while (re-search-forward dired-subdir-regexp nil t)
@@ -3730,8 +3736,7 @@ dired-build-subdir-alist
 	(unless (save-excursion
 		  (goto-char (match-beginning 0))
 		  (beginning-of-line)
-		  (forward-char 2)
-		  (looking-at-p dired-re-perms))
+		  (looking-at-p file-entry-beg-re))
 	  (save-excursion
 	    (goto-char (match-beginning 1))
 	    (setq new-dir-name