- 1 课程回顾
- 2 Emacs Dired文件管理
- 3 dirvish文件管理增强
- 4 通过Emacs来进行文件管理的基本操作
- 4.1 拷贝、粘贴、剪切文件(夹)
- 4.2 删除文件(夹)
- 4.3 创建文件(夹)
- 4.4 跳转文件(夹)
- 4.5 搜索文件(夹)的工作流
- 4.6 批量操作
- 4.7 改名
- 5 结语
1 课程回顾 🔗
上节课我们学习了如何在Emacs里通过Org mode来进行日程管理,我们可以在日常工作和生活中,将自己每天的计划安排结合日记一起记录下来,然后通过Org mode的机制进行追踪和提醒,刚开始肯定会有一些不习惯,但如果长期坚持下去,就会发现它的好处,它会让你养成一个良好的习惯,而所有的这些记录,都可追溯、可查询,而你在用的过程中也会感到喜悦!
今天我们来学习如何在Emacs里进行文件管理。
2 Emacs Dired文件管理 🔗
Emacs自带一个插件叫 Dired (Directory Editor),可以让Emacs对系统里的文件进行管理。我们可以通过 C-x d
来启动Dired。启动后,它会让你选择要进入哪个目录(默认为当前打开文件所在的目录):
我们对文件的常用操作大致有如下几种:
- 拷贝文件(夹)
- 剪切文件(夹)
- 粘贴文件(夹)
- 删除文件(夹)
- 创建文件(夹)
- 跳转文件(夹)
- 查找文件(夹)
- 批量操作文件(夹)
- 改名
- …
所有的这些操作都可以在Emacs里通过Dired、Consult、Embark等手段完成,非常方便。下面我们逐步来讲解如何配置和使用Dired。
2.1 Dired基础配置 🔗
(use-package dired
:ensure nil
:bind (:map dired-mode-map
("C-<return>" . xah-open-in-external-app)
("W" . dired-copy-path)
)
:config
;; Enable the disabled dired commands
(put 'dired-find-alternate-file 'disabled nil)
;; open files via external program based on file types, See:
;; https://emacs.stackexchange.com/questions/3105/how-to-use-an-external-program-as-the-default-way-to-open-pdfs-from-emacs
(defun xdg-open (filename)
(interactive "fFilename: ")
(let ((process-connection-type))
(start-process "" nil (cond ((eq system-type 'gnu/linux) "xdg-open")
((eq system-type 'darwin) "open")
((eq system-type 'windows-nt) "start")
(t "")) (expand-file-name filename))))
;; open files via external program when using find-file
(defun find-file-auto (orig-fun &rest args)
(let ((filename (car args)))
(if (cl-find-if
(lambda (regexp) (string-match regexp filename))
'(
;; "\\.html?\\'"
"\\.xlsx?\\'"
"\\.pptx?\\'"
"\\.docx?\\'"
"\\.mp4\\'"
"\\.app\\'"
))
(xdg-open filename)
(apply orig-fun args))))
(advice-add 'find-file :around 'find-file-auto)
(defun dired-copy-path ()
"In dired, copy file path to kill-buffer.
At 2nd time it copy current directory to kill-buffer."
(interactive)
(let (path)
(setq path (dired-file-name-at-point))
(if (string= path (current-kill 0 1)) (setq path (dired-current-directory)))
(message path)
(kill-new path)))
(defun xah-open-in-external-app (&optional @fname)
"Open the current file or dired marked files in external app.
The app is chosen from your OS's preference.
When called in emacs lisp, if @fname is given, open that.
URL `http://ergoemacs.org/emacs/emacs_dired_open_file_in_ext_apps.html'
Version 2019-11-04"
(interactive)
(let* (
($file-list
(if @fname
(progn (list @fname))
(if (or (string-equal major-mode "dired-mode")
(string-equal major-mode "dirvish-mode"))
(dired-get-marked-files)
(list (buffer-file-name)))))
($do-it-p (if (<= (length $file-list) 5)
t
(y-or-n-p "Open more than 5 files? "))))
(when $do-it-p
(cond
((string-equal system-type "windows-nt")
(mapc
(lambda ($fpath)
(w32-shell-execute "open" $fpath)) $file-list))
((string-equal system-type "darwin")
(mapc
(lambda ($fpath)
(shell-command
(concat "open " (shell-quote-argument $fpath)))) $file-list))
((string-equal system-type "gnu/linux")
(mapc
(lambda ($fpath) (let ((process-connection-type nil))
(start-process "" nil "xdg-open" $fpath))) $file-list))))))
:custom
;; (dired-recursive-deletes 'always)
(delete-by-moving-to-trash t)
(dired-dwim-target t)
(dired-bind-vm nil)
(dired-bind-man nil)
(dired-bind-info nil)
(dired-auto-revert-buffer t)
(dired-hide-details-hide-symlink-targets nil)
(dired-kill-when-opening-new-dired-buffer t)
(dired-listing-switches "-AFhlv"))
(use-package dired-aux
:ensure nil
:bind (:map dired-mode-map
("C-c +" . dired-create-empty-file))
:config
;; with the help of `evil-collection', P is bound to `dired-do-print'.
(define-advice dired-do-print (:override (&optional _))
"Show/hide dotfiles."
(interactive)
(if (or (not (boundp 'dired-dotfiles-show-p)) dired-dotfiles-show-p)
(progn
(setq-local dired-dotfiles-show-p nil)
(dired-mark-files-regexp "^\\.")
(dired-do-kill-lines))
(revert-buffer)
(setq-local dired-dotfiles-show-p t)))
:custom
(dired-isearch-filenames 'dwim)
(dired-create-destination-dirs 'ask)
(dired-vc-rename-file t))
(use-package dired-x
:ensure nil
:hook (dired-mode . dired-omit-mode)
:init
(setq dired-guess-shell-alist-user `((,(rx "."
(or
;; Videos
"mp4" "avi" "mkv" "flv" "ogv" "ogg" "mov"
;; Music
"wav" "mp3" "flac"
;; Images
"jpg" "jpeg" "png" "gif" "xpm" "svg" "bmp"
;; Docs
"pdf" "md" "djvu" "ps" "eps" "doc" "docx" "xls" "xlsx" "ppt" "pptx")
string-end)
,(cond ((eq system-type 'gnu/linux) "xdg-open")
((eq system-type 'darwin) "open")
((eq system-type 'windows-nt) "start")
(t "")))))
:custom
(dired-omit-verbose nil)
(dired-omit-files (rx string-start
(or ".DS_Store"
".cache"
".vscode"
".ccls-cache" ".clangd")
string-end))
;; Dont prompt about killing buffer visiting delete file
(dired-clean-confirm-killing-deleted-buffers nil)
)
2.2 Dired美化 🔗
2.2.1 diredfl多彩美化 🔗
默认的Dired只有两种颜色以区分文件和文件夹,我们可以使用 diredfl 插件让Dired变得更加多彩一些:
(use-package diredfl
:ensure t
:hook (dired-mode . diredfl-mode))
安装完后我们可以看到Dired多了不少其他的颜色,包括文件后缀名、文件夹、文件是否可写、文件的时间等:
2.2.2 all-the-icons-dired图标美化 🔗
我们通过 all-the-icons-dired 插件给Dired添加好看的图标。
我们需要先安装 all-the-icons.el 插件,这个插件能给Emacs很多地方如 find-file
加上好看的图标,安装完后,我们还需要通过 M-x all-the-icons-install-fonts
命令来安装相应的字体:
(use-package all-the-icons
:ensure t
:when (display-graphic-p)
:commands all-the-icons-install-fonts
)
然后我们安装 all-the-icons-dired
插件:
(use-package all-the-icons-dired
:ensure t
:hook (dired-mode . all-the-icons-dired-mode)
)
我们再次打开Dired后可以看到,所有的文件和文件夹都加上了好看的图标,通过不同的图标来区分各类文件和文件夹:
顺便我们通过 all-the-icons-completion 插件给迷你缓冲区的补全系统也加上好看的图标:
(use-package all-the-icons-completion
:ensure t
:hook ((after-init . all-the-icons-completion-mode)
(marginalia-mode . all-the-icons-completion-marginalia-setup))
)
3 dirvish文件管理增强 🔗
dirvish 是在Dired基础之上的文件管理增强插件。选择它而不选择 ranger.el 也是因为 dirvish
是基于原生 Dired 做的增强,所有的快捷键使用习惯等都与 Dired 保持一致。
- 需要通过
brew install poppler
安装 poppler 来预览PDF;- 需要通过
brew install ffmpegthumbnailder
来安装 ffmpegthumbnailer 来预览视频。
(use-package dirvish
:ensure t
:hook (after-init . dirvish-override-dired-mode)
:bind (:map dired-mode-map
("TAB" . dirvish-toggle-subtree)
("SPC" . dirvish-show-history)
("*" . dirvish-mark-menu)
("r" . dirvish-roam)
("b" . dirvish-goto-bookmark)
("f" . dirvish-file-info-menu)
("M-n" . dirvish-go-forward-history)
("M-p" . dirvish-go-backward-history)
("M-s" . dirvish-setup-menu)
("M-f" . dirvish-toggle-fullscreen)
([remap dired-sort-toggle-or-edit] . dirvish-quicksort)
([remap dired-do-redisplay] . dirvish-ls-switches-menu)
([remap dired-summary] . dirvish-dispatch)
([remap dired-do-copy] . dirvish-yank-menu)
([remap mode-line-other-buffer] . dirvish-other-buffer))
:config
(dirvish-peek-mode)
(setq dirvish-hide-details t)
;; open mp4 file via external program which is mpv here.
(add-to-list 'mailcap-mime-extensions '(".mp4" . "video/mp4"))
(add-list-to-list 'dirvish-open-with-programs '(
(("html") . ("open" "%f"))
(("xlsx") . ("open" "%f"))
(("pptx") . ("open" "%f"))
(("docx") . ("open" "%f"))
(("md") . ("open" "%f"))
))
:custom
(dirvish-menu-bookmarks '(("h" "~/" "Home")
("d" "~/Downloads/" "Downloads")
("e" "~/.emacs.d.default/" "Emacs")
("o" "~/org/" "org")
("i" "~/iCloud/" "iCloud")
;; ("t" "~/.local/share/Trash/files/" "TrashCan")
))
(dirvish-mode-line-format '(:left
(sort file-time " " file-size symlink) ; it's ok to place string inside
:right
;; For `dired-filter' users, replace `omit' with `filter' segment defined below
(omit yank index)))
(dirvish-attributes '(subtree-state
file-size
vc-state
git-msg
;; all-the-icons
))
)
我们安装配置完 dirvish
后,再次通过 C-x d
打开 Dired 后,可以看到整个界面变成了下面这样,非常简洁:
我们可以在 dirvish
界面按下 ?
来了解更多的快捷键和命令:
4 通过Emacs来进行文件管理的基本操作 🔗
按照前文所述,我们对文件的常用操作大致有如下几种,下面将逐一讲解如何通过 dirvish
来进行:
- 拷贝文件(夹)
- 剪切文件(夹)
- 粘贴文件(夹)
- 删除文件(夹)
- 创建文件(夹)
- 跳转文件(夹)
- 查找文件(夹)
- 批量操作文件(夹)
- 改名
- …
4.1 拷贝、粘贴、剪切文件(夹) 🔗
这几个操作在 dirvish
里都是一致的,我们可以通过 m
来标记我们要操作的文件或文件夹,然后我们跳转到需要粘贴或操作的目标文件夹,按 C
(dirvish-yank-menu
) 来选择具体的操作动作:
- Yank:粘贴到这里
- Move:剪切到这里
- Make symlinks: 设置软链接
- …
4.2 删除文件(夹) 🔗
我们只需要在目标文件(夹)的行按下 D
(dired-do-delete
) 就可以删除当前文件(夹),如果要多选,可以通过 m
(dired-mark
) 键来标记,然后再按下 D
键进行删除:
4.3 创建文件(夹) 🔗
我们按下 C-c +
(dired-create-empty-file
) 来创建一个空文件(相当于是 touch
命令的效果):
我们按下 +
(dired-create-directory
) 来在当前文件夹下创建一个新的文件夹:
4.4 跳转文件(夹) 🔗
我们按下 j
(dired-goto-file
) 来跳转到某个文件(夹):
4.5 搜索文件(夹)的工作流 🔗
我个人的使用习惯是先通过 consult-locate
来找到目的文件,然后通过 embark 插件来实现迷你缓冲区的类似右键的操作。
我们先来安装配置下 embark
:
(use-package embark
:ensure t
:bind (([remap describe-bindings] . embark-bindings)
("C-'" . embark-act)
:map minibuffer-local-map
:map minibuffer-local-completion-map
("TAB" . minibuffer-force-complete)
:map embark-file-map
("E" . consult-file-externally) ; Open file externally, or `we' in Ranger
("O" . consult-directory-externally) ; Open directory externally
)
:init
;; Optionally replace the key help with a completing-read interface
(setq prefix-help-command #'embark-prefix-help-command)
:config
;; Show Embark actions via which-key
(setq embark-action-indicator
(lambda (map)
(which-key--show-keymap "Embark" map nil nil 'no-paging)
#'which-key--hide-popup-ignore-command)
embark-become-indicator embark-action-indicator)
;; open directory
(defun consult-directory-externally (file)
"Open directory externally using the default application of the system."
(interactive "fOpen externally: ")
(if (and (eq system-type 'windows-nt)
(fboundp 'w32-shell-execute))
(shell-command-to-string (encode-coding-string (replace-regexp-in-string "/" "\\\\"
(format "explorer.exe %s" (file-name-directory (expand-file-name file)))) 'gbk))
(call-process (pcase system-type
('darwin "open")
('cygwin "cygstart")
(_ "xdg-open"))
nil 0 nil
(file-name-directory (expand-file-name file)))))
;; Hide the mode line of the Embark live/completions buffers
(add-to-list 'display-buffer-alist
'("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*"
nil
(window-parameters (mode-line-format . none))))
)
(use-package embark-consult
:ensure t
:hook (embark-collect-mode . consult-preview-at-point-mode))
我们以打开 在Emacs里进行文件管理.org
这个文件所在的文件夹Dired为例:
- 通过
consult-locate
输入#Emacs#wjgl
来定位此文件; - 按下
C-'
来触发embark-act
; - 在
embark
下按j
键跳转到相应的Dired。
通过这个工作流,我们就能很快速的跳转到硬盘上的任意一个文件所在的文件夹了,只要自己记得一些关键词即可。
4.6 批量操作 🔗
在 Dired
里,批量操作都是通过 m
键先进行对象的选择,然后再执行相应的动作,操作逻辑跟我们在 Finder
等文件管理器里的思路是一样的。
我们掌握了以上的常用文件操作,就可以通过 Emacs+Dired+Dirvish 进行高效的文件管理了,我们不再需要频繁的通过鼠标打开一个又一个的访达窗口了。
4.7 改名 🔗
我们将光标移动到目标文件或文件夹上,然后按下 R
(dired-do-rename
) 来进行改名:
5 结语 🔗
通过今天的课程,我们学习了如何在Emacs里高效的进行文件管理,通过Emacs强大的机制,我们通过键盘就能实现绝大多数的文件管理操作,简单快捷高效!
这节课的配置文件的快照见:emacs-config-l20.org
你也可以在 这里 查看最新的配置文件。