[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

"Renaming: permission denied" file-error in Windows

From: LynX
Subject: "Renaming: permission denied" file-error in Windows
Date: Sun, 11 Dec 2011 02:16:45 +0200
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv: Gecko/20100227 Thunderbird/3.0.3


I found that dired in Windows does not provide you possibility to move a directory to a new location if this new location resides on a different logical disk.

For instance you have two opened dired buffers: `c:\dir1' and `f:\dir2'. To move some files from `dir1' to `dir2' you can use "R", but if you try to move some directory from `dir1' to `dir2' you will get `Renaming: permission denied' error message.

The problem occurs when dired calls Emacs function which delegates the call to native POSIX function `rename'.

In Windows `rename' operates a bit different than in other systems. According to MSDN [http://msdn.microsoft.com/en-us/library/zw5t957f.aspx]:

-- "You can use rename to move a file from one directory or device to another by giving a different path in the newname argument. However, you cannot use rename to move a directory." --

Whereas, in standard POSIX spec such constraint was not found.

Following code workarounds this problem by wrapping dired function
`dired-rename-file'. So when `Renaming: permission denied' error occurs, it tries to move the directory again by moving each of it files recursively to a new destination, recreating the source directory with its subdirectory structure.

If it also fails to do this due to real permission problems then it sends original error message.


(defadvice dired-rename-file
  (around my-dired-rename-file
    (file newname ok-if-already-exists))
  "This advice definition helps to deal with
`Renaming: permission denied' error message when moving
directories between different logical disks in dired.
This is a Windows specific problem."
  (condition-case err
          (error-message-string err)
          "Renaming: permission denied")
        (file-directory-p file)
        (move-directory-recursively file newname)))))
(ad-activate 'dired-rename-file t)

(defun move-directory-recursively (dir-src dir-dst)
  "Moves directory DIR-SRC to the DIR-DST recursively.
To move directory dir1 into the directory dir2 you should
call this function like as follows:
  (move-directory-recursively `dir1' `dir2/dir1')
To move content of the directory dir1 into the directory
  (move-directory-recursively `dir1' `dir2')
If dir2 does not exist it will be created."
  (let ((queue (list (cons dir-src dir-dst)))
        dir-dst dir-src remove-later)
    (while queue
      (let ((dir-src-dst (car queue)))
        (setq dir-src (car dir-src-dst))
        (setq dir-dst (cdr dir-src-dst)))
      (setq queue (cdr queue))
      ;; if dir-dst is a file signal an error
        (file-exists-p dir-dst)
        (not (file-directory-p dir-dst))
        (signal 'file-error
          (format "Error: file %s exist" dir-dst)))
      ;; if dir-dst does not exist - create it
      (if (not (file-exists-p dir-dst))
        (make-directory dir-dst))
      (dolist (file (directory-files dir-src))
          (not (string= file "."))
          (not (string= file ".."))
          (let ((path (concat dir-src "/" file)))
            (if (file-directory-p path)
              ;; it is a directory
                ;; place it to the queue
                (setq queue
                    (cons path (concat dir-dst "/" file))
                ;; and store it path to remove it later
                (push path remove-later))
              ;; not a dir
                  (format "Moving %s to %s" path dir-dst))
                (rename-file path dir-dst)))))))
  ;; after we moved all content we can remove the
  ;; empty directories in dir-src
  (dolist (dir remove-later)
    (condition-case err
      (dired-delete-file dir 'always)
      (error ;; catch errors from failed deletions
        (dired-log "%s\n" err)))))
  (dired-delete-file dir-src 'always))

reply via email to

[Prev in Thread] Current Thread [Next in Thread]