Dired: Duplicate Files (операция, а не способ избавиться от них)

Иногда я хочу создать дубликат ряда файлов (скажем, файлов конфигурации), которые изначально должны иметь то же содержимое, что и исходные файлы. Поэтому я хотел бы иметь возможность пометить некоторые файлы в dired и «продублировать» их, эта процедура дублирования может работать аналогично процедуре дублирования, используемой большинством файловых менеджеров, при вставке в исходный каталог: имена дублированных файлов получают " (Копировать)" (непосредственно перед расширением файла).

Кажется, я не могу найти встроенную функцию dired, которая делает это, может быть, кто-то может помочь/уже создал такую ​​​​функцию?

Помощь очень ценится!


person elemakil    schedule 02.07.2013    source источник


Ответы (3)


Может быть, вы захотите переименовать функции (я не придумал лучших имен), может быть, какое-то более сложное форматирование, если хотите...

(defcustom dired-keep-marker-version ?V
  "Controls marking of versioned files.
If t, versioned files are marked if and as the corresponding original files were.
If a character, copied files are unconditionally marked with that character."
  :type '(choice (const :tag "Keep" t)
         (character :tag "Mark"))
  :group 'dired-mark)

(defun dired-version-file (from to ok-flag)
  (dired-handle-overwrite to)
  (dired-copy-file-recursive from to ok-flag dired-copy-preserve-time t
                 dired-recursive-copies))

(defun dired-do-version (&optional arg)
  "Search for numeric pattern in file name and create a version of that file
with that number incremented by one, or, in case such file already exists,
will search for a file with the similar name, incrementing the counter each
time by one.
Additionally, if called with prefix argument, will prompt for number format.
The formatting is the same as is used with `format' function."
  (interactive "P")
  (let ((fn-list (dired-get-marked-files nil nil)))
    (dired-create-files
     (function dired-version-file) "Version" fn-list
     (function
      (lambda (from)
        (let (new-name (i 0) (fmt (if arg (read-string "Version format: " "%d") "%d")))
          (while (or (null new-name) (file-exists-p new-name))
            (setq new-name
                  (if (string-match  "^\\([^0-9]*\\)\\([0-9]+\\)\\(.*\\)$" from)
                      (concat (match-string 1 from)
                              (format fmt
                                      (+ (string-to-number (match-string 2 from)) (1+ i)))
                              (match-string 3 from))
                    (concat from (format (concat "." fmt) i)))
                  i (1+ i))) new-name)))
     dired-keep-marker-version)))

(define-key dired-mode-map (kbd "c") 'dired-do-version)

Кроме того, я изначально использовал v для привязки этой функции, потому что я не использую dired-view, но вам нужно будет привязать это внутри хука direds. c просто был первым неопределенным ключом, поэтому я использовал его.

person Community    schedule 02.07.2013
comment
Да! Определенно очень крутой фрагмент! Я подумал о двух дополнениях: 1) при вызове с префиксом C-u запросить строку вместо числа и 2) проверить, существует ли уже версия, и соответственно увеличить ее. Я не знаю, насколько сложным и трудоемким может быть добавление этих функций.... - person elemakil; 03.07.2013
comment
@elemakil в настоящее время предлагает вам переименовать файл, если только что созданное имя существует ... хотя, возможно, может быть автоматическое разрешение ... Я посмотрю на это позже сегодня. Во время написания этого фрагмента я обнаружил, каково поведение по умолчанию многих dired команд... :) C-u для них означает, что если есть отмеченный каталог, он будет использовать этот каталог в качестве цели. Но, конечно, с префиксом можно сделать больше. Вечером еще разберусь. - person ; 03.07.2013
comment
@elemakil, обе вещи оказались проще, чем я думал. В целом вроде работает, но если заметите какие-либо проблемы с этим, можете предупредить меня :) Не похоже, что эта функция может причинить какой-либо вред, так как она не удаляет файлы и не перезаписывает, но я d все еще будьте осторожны, на всякий случай. - person ; 03.07.2013

Есть одна функция, которая делает то, что вы хотите: dired-do-copy-regexp

Пример использования:

  1. пометить файлы
  2. M-x dired-do-copy-regexp
  3. \(.*\)\.\(.*\)
  4. \1 (copy).\2

Для файла с именем foo.txt вы создадите другой файл с именем foo (copy).txt.

Обратите внимание, что мое первое регулярное выражение имеет две группы, а второе регулярное выражение ссылается на них. При необходимости можно делать гораздо более сложные вещи.

person juanleon    schedule 02.07.2013
comment
Мне это нравится! Красиво и просто и напоминает мне, что я всегда должен попробовать что-то с регулярными выражениями, прежде чем публиковать вопрос на SO... ;-) Однако я предполагаю, что это нельзя расширить, чтобы автоматически определять, присутствует ли уже (copy) (а не файл, который помечен), и если это верно, добавляется больше (copy) строк, пока имя файла не станет уникальным? [Не то чтобы я когда-либо действительно использовал это... вашего первоначального решения достаточно, однако мне любопытно]. - person elemakil; 02.07.2013
comment
Если вы хотите обработать случай, когда присутствует копия, вам следует взглянуть на переменные dired-backup-overwrite (из dired-aux.el) и backup-directory-alist. Первый управляет созданием резервных копий перед перезаписью файлов, а второй определяет, как назвать резервные копии. - person juanleon; 03.07.2013
comment
Пункт 3 выглядит как группа поддержки - person Richard de Wit; 17.03.2016

В режиме Dired поместите курсор на файл, который вы хотите продублировать, или отметьте этот файл, затем нажмите «C». Вам будет предложено ввести новое имя.

Вы также можете использовать эту функцию для копирования файлов между буферами Dired. Чтобы это было возможно, поместите в свой файл инициализации: (setq dired-dwim-target t)

person Navidot    schedule 04.05.2018
comment
Но при этом вы не можете дублировать несколько файлов. -Или я не понял, как переименовать несколько файлов - person Swedgin; 22.09.2020