Function: dired-mark-sexp

dired-mark-sexp is an interactive and byte-compiled function defined in dired-x.el.gz.

Signature

(dired-mark-sexp PREDICATE &optional UNFLAG-P)

Documentation

Mark files for which PREDICATE returns non-nil.

With a prefix arg, unmark or unflag those files instead.

PREDICATE is a Lisp expression that can refer to the following symbols:

    inode [integer] the inode of the file (only for ls -i output)
    s [integer] the size of the file for ls -s output
                     (usually in blocks or, with -k, in KByte)
    mode [string] file permission bits, e.g. "-rw-r--r--"
    nlink [integer] number of links to file
    uid [string] owner
    gid [string] group (If the gid is not displayed by ls,
                     this will still be set (to the same as uid))
    size [integer] file size in bytes
    time [string] the time that ls displays, e.g. "Feb 12 14:17"
    name [string] the name of the file
    sym [string] if file is a symbolic link, the linked-to name, else ""

For example, use

        (equal 0 size)

to mark all zero length files.

There's an ambiguity when a single integer not followed by a unit prefix precedes the file mode: It is then parsed as inode number and not as block size (this always works for GNU coreutils ls).

Another limitation is that the uid field is needed for the function to work correctly. In particular, the field is not present for some values of ls-lisp-emulation.

This function operates only on the buffer content and does not refer at all to the underlying file system. Contrast this with find-dired, which might be preferable for the task at hand. If the region is active in Transient Mark mode, mark files only in the active region if dired-mark-region is non-nil.

Key Bindings

Source Code

;; Defined in /usr/src/emacs/lisp/dired-x.el.gz
(defun dired-mark-sexp (predicate &optional unflag-p)
  "Mark files for which PREDICATE returns non-nil.
With a prefix arg, unmark or unflag those files instead.

PREDICATE is a Lisp expression that can refer to the following symbols:

    inode  [integer] the inode of the file (only for ls -i output)
    s      [integer] the size of the file for ls -s output
                     (usually in blocks or, with -k, in KByte)
    mode   [string]  file permission bits, e.g. \"-rw-r--r--\"
    nlink  [integer] number of links to file
    uid    [string]  owner
    gid    [string]  group  (If the gid is not displayed by ls,
                     this will still be set (to the same as uid))
    size   [integer] file size in bytes
    time   [string]  the time that ls displays, e.g. \"Feb 12 14:17\"
    name   [string]  the name of the file
    sym    [string]  if file is a symbolic link, the linked-to name, else \"\"

For example, use

        (equal 0 size)

to mark all zero length files.

There's an ambiguity when a single integer not followed by a unit
prefix precedes the file mode: It is then parsed as inode number
and not as block size (this always works for GNU coreutils ls).

Another limitation is that the uid field is needed for the
function to work correctly.  In particular, the field is not
present for some values of `ls-lisp-emulation'.

This function operates only on the buffer content and does not
refer at all to the underlying file system.  Contrast this with
`find-dired', which might be preferable for the task at hand.
If the region is active in Transient Mark mode, mark files
only in the active region if `dired-mark-region' is non-nil."
  ;; Using sym="" instead of nil avoids the trap of
  ;; (string-match "foo" sym) into which a user would soon fall.
  ;; Give `equal' instead of `=' in the example, as this works on
  ;; integers and strings.
  (interactive
   (list (read--expression
          (format "%s if (lisp expr): "
                  (if current-prefix-arg
                      "UNmark"
                    "Mark")))
         current-prefix-arg)
   dired-mode)
  (message "%s" predicate)
  (let ((dired-marker-char (if unflag-p ?\040 dired-marker-char))
        inode s mode nlink uid gid size time name sym)
    (dired-mark-if
     (save-excursion
       (and
        ;; Sets vars
        ;;                inode s mode nlink uid gid size time name sym

        ;; according to current file line.  Returns t for success, nil if
        ;; there is no file line.  Upon success, all variables are set, either
        ;; to nil or the appropriate value, so they need not be initialized.
        ;; Moves point within the current line.
        (dired-move-to-filename)
        (let ((mode-len 10) ; length of mode string
	      ;; like in dired.el, but with subexpressions \1=inode, \2=s:
	      ;; GNU ls -hs suffixes the block count with a unit and
	      ;; prints it as a float, FreeBSD does neither.
	      (dired-re-inode-size "\\=\\s *\\([0-9]+\\s +\\)?\
\\(?:\\([0-9]+\\(?:\\.[0-9]*\\)?[BkKMGTPEZYRQ]?\\)? ?\\)"))
	  (beginning-of-line)
	  (forward-char 2)
	  (search-forward-regexp dired-re-inode-size nil t)
          ;; XXX Might be a size not followed by a unit prefix.
          ;; We could set s to inode if it were otherwise nil,
          ;; with a similar reasoning as below for setting gid to uid,
          ;; but it would be even more whimsical.
	  (setq inode (when (match-string 1)
			(string-to-number (match-string 1))))
	  (setq s (when (match-string 2)
		    (dired-x--string-to-number (match-string 2))))
          (setq mode (buffer-substring (point) (+ mode-len (point))))
          (forward-char mode-len)
          ;; Skip any extended attributes marker ("." or "+").
          (or (= (following-char) ?\s)
              (forward-char 1))
          (setq nlink (read (current-buffer)))
          ;; Karsten Wenger <kw@cis.uni-muenchen.de> fixed uid.
          ;; Another issue is that GNU ls -n right-justifies numerical
          ;; UIDs and GIDs, while FreeBSD left-justifies them, so
          ;; don't rely on a specific whitespace layout.  Both of them
          ;; right-justify all other numbers, though.
          ;; XXX Return a number if the uid or gid seems to be
          ;; numerical?
          (setq uid (buffer-substring (progn
                                        (skip-chars-forward " \t")
                                        (point))
                                      (progn
                                        (skip-chars-forward "^ \t")
                                        (point))))
	  (dired-move-to-filename)
          (save-excursion
            (setq time
                  ;; The regexp below tries to match from the last
                  ;; digit of the size field through a space after the
                  ;; date.  Also, dates may have different formats
                  ;; depending on file age, so the date column need
                  ;; not be aligned to the right.
                  (buffer-substring (save-excursion
                                      (skip-chars-backward " \t")
                                      (point))
                                    (progn
                                      (re-search-backward
                                       directory-listing-before-filename-regexp)
                                      (skip-chars-forward "^ \t")
                                      (1+ (point))))
                  size (dired-x--string-to-number
                        ;; We know that there's some kind of number
                        ;; before point because the regexp search
                        ;; above succeeded.  I don't think it's worth
                        ;; doing an extra check for leading garbage.
                        (buffer-substring (point)
                                          (progn
                                            (skip-chars-backward "^ \t")
                                            (point))))
                  ;; If no gid is displayed, gid will be set to uid
                  ;; but the user will then not reference it anyway in
                  ;; PREDICATE.
                  gid (buffer-substring (progn
                                          (skip-chars-backward " \t")
                                          (point))
                                        (progn
                                          (skip-chars-backward "^ \t")
                                          (point)))))
	  (setq name (buffer-substring (point)
				       (or
					(dired-move-to-end-of-filename t)
					(point)))
		sym (if (looking-at " -> ")
			(buffer-substring (progn (forward-char 4) (point))
					  (line-end-position))
		      ""))
          t)
        (eval predicate
              `((inode . ,inode)
                (s . ,s)
                (mode . ,mode)
                (nlink . ,nlink)
                (uid . ,uid)
                (gid . ,gid)
                (size . ,size)
                (time . ,time)
                (name . ,name)
                (sym . ,sym)))))
     (format "'%s file" predicate))))