Emacs 26.1, Windows 10, Dired+
How to append contents of multiple files in one folder into one file?
Emacs 26.1, Windows 10, Dired+
How to append contents of multiple files in one folder into one file?
One way to get it done is Shell Commands in Dired, together with cat:
C-x dmRun a shell command by hitting ! and typing the command: cat ? >> /path/to/accumulate-file.txt
The ? surrounded with whitespaces means running the shell command once for each marked files,
with ? being replaced by the file name.
Here's a function that appends the contents of each file under DIR and writes the results into a result.txt file in the same directory.
(defun append-file-contents (dir)
(interactive "DDirectory: ")
(let (contents
(default-directory dir)
(files (directory-files dir nil "^\\([^#.~]\\)")))
(dolist (file files)
(when (file-regular-p file)
(push (with-temp-buffer
(insert-file-contents file)
(buffer-string))
contents)))
(write-region (mapconcat #'identity contents "\n")
nil (concat dir "result.txt"))))
directory-files-recursively instead of directory-files and see if that works.
– jagrg
Mar 19 '19 at 22:02
(directory-files-recursively dir "."). Also, the line (default-directory dir) is probably not needed.
– jagrg
Mar 20 '19 at 12:11
Open the buffer where you want to insert the files and put point where you want the text to be inserted.
Find the directory with the files, i.e., C-x C-f. The directory is shown in a dired buffer.
Mark the files with m.
a. You can also mark with % m if you want to select the files by a regular expression.
b. You can also use % g if you want to mark files containing matches for a given regular expression.
The basic lisp code that provides you with the list of marked files is:
(dired-get-marked-files)
The files have the same order as in the dired buffer. You can also sort in other ways with cl-sort.
Insert files from the list into your target buffer. Therefore run the following lisp code with the dired buffer current:
(dolist (fn (dired-get-marked-files)) (with-current-buffer "target-buffer-name" (insert-file fn)))
Note:
a. You have to replace "target-buffer-name" by the name of your target buffer. Often that is the file name of your target file.
b. For this command to work the buffer with name "target-buffer-name" must already exists.
c. If you want to create a new buffer use (get-buffer-create "target-buffer-name") instead.
You can run the elisp expressions in the current buffer easily with the key sequence M-:. You just input the elisp expression in the minibuffer and run it by pressing the RET button.
insert-file says: Don’t call it from programs! Use ‘insert-file-contents’ instead. , so maybe insert-file-contents is better?
– whatacold
Feb 08 '19 at 12:11
(dired-get-marked-files) seem more intuitive to me to get the file lists, and it returns them as in the buffer top-down.
– whatacold
Feb 08 '19 at 12:18
(dired-map-over-marks ...) by (dired-get-marked-files). I know about insert-file-contents and opted for insert-files because it works and it is shorter. At this point one just needs the job to be done.
– Tobias
Feb 08 '19 at 12:26
dired-get-marked-files is from dired+.el which is not necessarily installed. Therefore I will add my original solution again.
– Tobias
Feb 08 '19 at 12:33
dired-get-marked-files in dired.el in Emacs 26.1, at least. dired+.el provides another one replacing it, see https://github.com/emacsmirror/dired-plus/blob/master/dired%2B.el#L2498
– whatacold
Feb 08 '19 at 12:41
dired-mode for that. Just use M-! if that works for you. The solution I offered is elisp only and works independently of the OS.
– Tobias
Feb 08 '19 at 14:23
...And then there is the Eshell-way. It uses Elisp under the hood when needed. Therefore it is OS-independent:
Open an Eshell via M-x eshell.
Change directory in the Eshell to the one you want with cd YourDirectoryPath.
Concatenate all files you want in Eshell with cat Pattern*Of*Source*Files > targetFile.
Note, emacs -Q uses Elisp for all above steps under Ubuntu (WSL):
~ $ which cd
eshell/cd is a compiled Lisp function in ‘em-dirs.el’.
~ $ which cat
eshell/cat is a compiled Lisp function in em-unix.el.
Open file1.txt using C-x C-f (find-file). Press M-! to execute shell-command. The command you want to execute is copy:
copy /b file1.txt + file2.txt + file2.txt file1.txt
Reload the buffer using M-x revert-buffer to see that indeed the files were appended. Beware! The copy command will overwrite file1.txt.
If you don't have file1.txt open, then the default-directory will not be for the correct folder. You would need to either issue cd first to change the default directory for the current buffer or use absolute paths.
cat. If you have Gitbash installed, though, then you do and it's likely on the path. You could use type, though. https://stackoverflow.com/questions/60244/is-there-replacement-for-cat-on-windows
– Lorem Ipsum
Feb 08 '19 at 13:48
For completeness, as sometimes the crudest of methods is the most appropriate...
C-x C-f (find-file)C-x h (mark-whole-buffer)M-w (kill-ring-save)C-x C-f (find-file)M-> (end-of-buffer)C-y (yank)At this point, you could save over the original first file using C-x C-s (save-file) or save a copy using C-x C-w (write-file). Repeat this as needed for all the files.
cat, it seems I'm wrong from OP's comment. I am trying to do it in elisp way. – whatacold Feb 08 '19 at 11:34catas you mentioned in other comment, then I don't understand why this error. Is there any other app "lock" the files? Doescatwork in Git Bash? – whatacold Feb 08 '19 at 14:04