必備的 Dired 設定與簡易教學

Dired 代表 “DIRectory EDitor” 的縮寫,是 Emacs 內建的一個功能完整而強大的檔案管理員(自訂的彈性更是其他 FM 沒得比的)。
我想他唯一的弱點是圖片顯示以及設定麻煩,不過本篇應該能夠幫你搞定大部分必要的設定。

我認為 Dired 是 Emacs 最獨特、吸引人、且最令人上癮與依賴的殺手級功能之一(就我所知目前還沒有其他編輯器有同等強大的工具)。相信聽過 Emacs 的很多人都會聽過 Emacser 的這種讚美,但當你實際想用時卻發現,C-h m 一看文件指令一大堆,而且很多指令名看不出來是做什麼的,根本不知從何下手。因此現在讓我們直奔主題:

最常用的命令

怎麼開啟 Dired? C-x C-f 後不要選檔案、還在目錄時直接按下 Enter 就是了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
g: 重新整理
+: 新增目錄
s: 按照時間/檔名排序檔案
^: 回到上層目錄

m: 標記多個檔案
u: 取消標記
U: 清除所有標記
R: 重新命名/移動(概念與 Unix 下的 mv 相同)
C: 拷貝檔案

!: 執行外部命令
&: 非同步地(asynchronously)執行外部命令

D: 刪除單一檔案
d: 標記多個檔案為刪除
x: 套用刪除

X: 解壓縮

必備設定檔


但只知道這些是不夠的。沒辦法,說實話沒設定過的 Dired 難用得連我家的貓都不想用。因此這裡整理了一些(我認為且推薦)必備的 Dired 相關設定,設定以後 Dired 立刻順手 n 倍:

請記得先去安裝 Dired+ ,他提供了 Dired 非常多的額外功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
(require 'dired)
(require 'dired-x) ;這行請記得加,不然無法使用隱藏檔案等功能。
(require 'dired+) ;請記得安裝 dired+,沒安裝的是笨蛋

;; 讓 Dired 有「多欄式」效果:用 C-x 3 在螢幕上開兩個 dired 視窗(如
;; 附圖),再來只要按 R 或 C(移動/複製檔案)時,會自動以另一個視窗為
;; 預設目標路徑。
(setq dired-dwim-target t)

;; 目錄排在檔案之前。
(defun dired-directory-sort ()
"Dired sort hook to list directories first."
(save-excursion
(let (buffer-read-only)
(forward-line 2) ;; beyond dir. header
(sort-regexp-fields t "^.*$" "[ ]*." (point) (point-max))))
(and (featurep 'xemacs)
(fboundp 'dired-insert-set-properties)
(dired-insert-set-properties (point-min) (point-max)))
(set-buffer-modified-p nil))

(add-hook 'dired-after-readin-hook 'dired-directory-sort)

;; 按 q 回到上層目錄,並自動把 cursor 移動到前一個目錄處
(defun my-dired-backward ()
"Go back to the parent directory (..), and the cursor will be moved to where
the previous directory."
(interactive)
(let* ((DIR (buffer-name)))
(if (equal DIR "*Find*")
(quit-window t)
(progn (find-alternate-file "..")
(re-search-forward DIR nil :no-error)
(revert-buffer)))))
(define-key dired-mode-map (kbd "q") 'my-dired-backward)


;; 按 Enter 時 Dired 時不會一直開新的 Dired buffer(按 Enter 時只用同一個 Dired 開目錄)
(defun dired-my-find-alternate-file ()
(interactive)
(if (file-regular-p (dired-get-filename))
(dired-find-file)
(dired-find-alternate-file)))
(define-key dired-mode-map (kbd "RET") 'dired-my-find-alternate-file) ; 按 Enter 開檔案
(put 'dired-find-alternate-file 'disabled nil) ; 避免 Dired 問你一些囉唆的問題

;;自動隱藏以.開頭的檔案(使用 C-x M-o 顯示/隱藏)
(setq dired-omit-files "^\\...+$")

;; Dired Omit 加強:
;; 簡單來說,這個能夠紀錄下目前的「隱藏狀態」,所以當你按
;; C-x M-o 隱藏以.為開頭的檔案後,即使到了不同目錄下,以.開頭的檔案
;; 依舊是處於隱藏狀態,直到你重新按 C-x M-o 為止。
(defvar v-dired-omit t
"If dired-omit-mode enabled by default. Don't setq me.")
(defun dired-omit-and-remember ()
"This function is a small enhancement for `dired-omit-mode', which will
\"remember\" omit state across Dired buffers."
(interactive)
(setq v-dired-omit (not v-dired-omit))
(dired-omit-auto-apply)
(revert-buffer))

(defun dired-omit-auto-apply ()
(setq dired-omit-mode v-dired-omit))

(define-key dired-mode-map (kbd "C-x M-o") 'dired-omit-and-remember)
(add-hook 'dired-mode-hook 'dired-omit-auto-apply)

;;使用 KB, MB 等方式顯示檔案大小(這個應該是 Unix 限定...Windows 我不
;;知該怎麼辦)。
(setq dired-listing-switches "-alh")

;; 和 KDE 的 Dolphin 一樣的檔案名過濾器,按 C-i 使用。 (by letoh)
(defun dired-show-only (regexp)
(interactive "sFiles to show (regexp): ")
(dired-mark-files-regexp regexp)
(dired-toggle-marks)
(dired-do-kill-lines))
(define-key dired-mode-map (kbd "C-i") 'dired-show-only)

;; 遞迴拷貝/複製檔案時的確認訊息設定
(setq dired-recursive-copies 'always) ; 拷貝檔案;「always」 表示永不詢問。
(setq dired-recursive-deletes 'top) ; 刪除檔案:「top」表示同一批檔案只詢問一次。

;; M-Enter 呼叫外部程式(此處是透過 `kde-open`)來開啟檔案,如果你不是
;; 用 KDE,可以改成 xdg-open 之類的。Windows 我不知該怎麼辦啦啦啦。
(defun dired-open-file-with-external-program ()
"Open file with external program in dired"
(interactive)
(let* ((file (dired-get-filename nil t)))
(message "Opening %s..." file)
(call-process "kde-open" nil 0 nil file)
(message "Opening %s done" file)))
(define-key dired-mode-map (kbd "M-RET") 'dired-open-file-with-external-program)

;; 在 Dired 下 C-x C-j 使用`kde-open`等外部程式開啟「當前目錄」
(defun open-current-directory-with-external-program ()
"Open current directory with external program."
(interactive)
(call-process "kde-open" nil 0 nil (file-truename default-directory)))
(define-key dired-mode-map (kbd "C-x C-j") 'open-current-directory-with-external-program)

;; 使用 f 搜尋目前目錄(這個部份可能也是 Unix 限定)
(define-key dired-mode-map "f" 'dired-find-name-in-current-directory)
(defun dired-find-name-in-current-directory ()
(interactive)
(find-name-dired default-directory
(format "*%s*" (read-from-minibuffer "Pattern: ")))
(set-buffer-multibyte t))
(setq find-name-arg "-iname")

;; 修正*Find*裡的中文亂碼問題
(setq find-ls-option '("-print0 | xargs -0 ls -ald" . ""))

;; 手動開系統的外接硬碟掛載目錄很麻煩,乾脆弄個快速鍵,C-c m 直接開
;; /var/rum/media(如果你的系統掛載路徑不在這,請自行修改)
(defun dired-open-mounted-media-dir ()
(interactive)
(find-file "/var/run/media/"))
(define-key dired-mode-map (kbd "C-c m") 'dired-open-mounted-media-dir)

;; 按 s 排序檔案,會先問你要根據什麼屬性排序,而且紀錄下排序狀態,不會
;; 跨 buffer 就不見了。
(defun dired-sort-size ()
"Dired sort by size."
(interactive) (dired-sort-other (concat dired-listing-switches "S")))
(defun dired-sort-extension ()
"Dired sort by extension."
(interactive) (dired-sort-other (concat dired-listing-switches "X")))
(defun dired-sort-ctime ()
"Dired sort by create time."
(interactive) (dired-sort-other (concat dired-listing-switches "ct")))
(defun dired-sort-utime ()
"Dired sort by access time."
(interactive) (dired-sort-other (concat dired-listing-switches "ut")))
(defun dired-sort-time ()
"Dired sort by time."
(interactive) (dired-sort-other (concat dired-listing-switches "t")))
(defun dired-sort-name ()
"Dired sort by name."
(interactive) (dired-sort-other (concat dired-listing-switches "")))

(defvar v-dired-sort 'name)
(defun dired-sort-and-remember ()
""
(interactive)
(setq v-dired-sort
(intern
(completing-read "Sort by: " '(name size extension ctime utime time) nil t
(cond ((eq v-dired-sort 'name) "time")
((eq v-dired-sort 'time) "name")
((eq v-dired-sort 'size) "name")
(t nil)))))
(dired-sort-auto-apply))

(defun dired-sort-auto-apply ()
(cond ((eq v-dired-sort 'name) (dired-sort-name))
((eq v-dired-sort 'size) (dired-sort-size))
((eq v-dired-sort 'extenstion) (dired-sort-extenstion))
((eq v-dired-sort 'ctime) (dired-sort-ctime))
((eq v-dired-sort 'utime) (dired-sort-utime))
((eq v-dired-sort 'time) (dired-sort-time))))

(add-hook 'dired-mode-hook 'dired-sort-auto-apply)
(define-key dired-mode-map "s" 'dired-sort-and-remember)

;; 看動畫很方便 ˊ・ω・ˋ 按 M-a 把檔案加入 SMPlayer 的播放清單中。
(defun dired-add-to-smplayer-playlist ()
"Add a multimedia file or all multimedia files under a directory into SMPlayer's playlist via Dired."
(interactive)
(require 'cl)
(let* ((PATTERN "\\(\\.mp4\\|\\.flv\\|\\.rmvb\\|\\.mkv\\|\\.avi\\|\\.rm\\|\\.mp3\\|\\.wav\\|\\.wma\\|\\.m4a\\|\\.mpeg\\|\\.aac\\|\\.ogg\\|\\.flac\\|\\.ape\\|\\.mp2\\|\\.wmv\\|.m3u\\|.webm\\)$")
(FILE (dired-get-filename nil t)))
(if (file-directory-p FILE) ;if it's a dir.
(let* ((FILE_LIST (directory-files FILE t PATTERN))
(n 0)
s_FILE_LIST)
(dolist (x FILE_LIST)
(if (not (or (equal x ".") (equal x "..")))
(setq s_FILE_LIST (concat s_FILE_LIST "'" x "' ")))
(setq n (1+ n)))
(message "Opening %s files..." n)
(call-process-shell-command "smplayer -add-to-playlist" nil nil nil (format "%s &" s_FILE_LIST)))
(if (string-match PATTERN FILE) ;if it's a file
(call-process "smplayer" nil 0 nil "-add-to-playlist" FILE)
(message "This is not a supported audio or video file."))))
(dired-next-line 1))
(define-key dired-mode-map (kbd "M-a") 'dired-add-to-smplayer-playlist)

經過這些調校以後,現在多了這些功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
(: 隱藏/顯示詳細資訊(Emacs24.4 安裝 Dired+ 後,會自動把檔名以外的部份隱藏起來,很方便)

RET: 使用同一個 Dired buffer 開啟目錄。
q: 回到上層目錄。

C-x M-o: 隱藏/顯示檔案(會紀錄當前隱藏狀態)。
s: 選擇檔案排序方式(且會紀錄當前排序狀態)。

C-i: 過濾目前目錄下的檔案名稱。

M-RET: 使用 kde-open 開啟檔案。
C-x C-j:(在 Dired 中)使用外部檔案管理員開啟目前目錄。
C-x C-j:(在檔案中)使用 Dired 開啟目前目錄,並 jump 到目前檔案位置。

f: 遞迴搜尋目前目錄下的檔案。

C-c m: 打開系統外接裝置的掛載路徑。

M-a: 把檔案加入 SMPlayer 的播放清單中。

現在應該順手很多了吧? ˊ・ω・ˋ
Dired 的功能還有很多很多,像是 mark 起來的檔案批次處理之類的,不過其實我最常用的也就以上這些功能,只要能夠活用,相信 Dired 應該會成為你非常重要的工具。有興趣的可以在 Dired 中按C-h m再慢慢研究還有什麼功能。如有覺得不錯的也請不吝分享:-)。


[2014-06-26 木 13:30] 感謝 cadeskao 的修改 =w=