2013-01-12 12 views
6

Vorrei scendere in modo ricorsivo dalla struttura della directory da un punto particolare e chiamare la directory di aggiornamento del copyright ad ogni livello.Esiste una funzione inclusa in Emacs per percorrere in modo ricorsivo la struttura della directory e chiamare una funzione?

Esiste una funzione inclusa in Emacs 24 che potrebbe essere d'aiuto? Per esempio qualcosa come:

(recursive-directory-walk "~/src/foo" '(copyright-update-directory)) 

Se non esiste tale funzione, alcune indicazioni su come iniziare l'attuazione del presente (o un'implementazione di lavoro) sarebbe grande.

risposta

3

Non so se esiste, ma non è molto difficile da scrivere.

(defun folder-dirs (folder) 
    (delete-if-not 'file-directory-p 
    (mapcar (lambda(arg) (file-name-as-directory (concat (file-name-as-directory folder) arg))) 
     (delete-if (lambda (arg) (or (string= ".." arg) (string= "." arg))) 
     (directory-files folder))))) 

(defun recursively-run-on-every-dir (fn folder) 
"FN - function, taking one argument; 
FOLDER - initial forder" 
    (funcall fn folder) 
    (mapc (lambda(arg) (recursively-run-on-every-dir fn arg)) 
    (folder-dirs folder)) 
    nil) 

;; use your function instead of print 
(recursively-run-on-every-dir 'print "/your/initial/path/") 
+0

Sembra che questo sia vicino, ma in realtà non esegue la funzione nella posizione iniziale. –

+0

Inoltre, questo in realtà non sembra fare nulla se utilizzo la directory di aggiornamento del copyright come funzione, ad es. (copyright-update-directory arg "*"). Stampa i nomi delle directory nell'area dei messaggi, ma nessun copyright sembra essere aggiornato. –

+0

Modificato, quindi viene eseguito nella posizione iniziale ora. Si dovrebbe passare la funzione di un argomento. Questo argomento è il percorso assoluto della cartella. – desudesudesu

2

Basta usare find-lisp

(require 'find-lisp) 

;; a simple function, just to test 
(defun my-funct (x) 
    (princ x) 
    (terpri)) 

(mapc 'my-funct (find-lisp-find-files "~/src/foo/" "\\.txt$")) 
3

La biblioteca f.el (github) su Melpa contiene funzioni per file system attraversamento.

(mapc 'copyright-update-directory (f-directories "~/path" nil t)) 

Discenderà la gerarchia di directory in modo ricorsivo. Vedere la documentazione per f-directories.

1

Penso che Chris Barrett's answer è giusto e uno idiomatico. Tuttavia, per scopi didattici volevo implementare Python os.walk, una funzione generale per il vasto attraversamento di alberi di directory. Ho usato la libreria di lista dash.el e le librerie di file e directory f.el. Questa è un'implementazione basata su stack translated from Python.

(defun walk (path) 
    (let ((stack (list (f-full path))) 
     result) 
    (while stack 
     (let* ((path (pop stack)) 
      (ds_ (f-directories path)) 
      (ds (-map 'f-relative ds_)) 
      (fs (-map 'f-relative (f-files path)))) 
     (--each ds_ (!cons it stack)) 
     (!cons (list path ds fs) result))) 
    (reverse result))) 

vedere Funzioni: f-full, pop, f-directories, f-relative, f-files, --each, !cons, reverse. Ora si può utilizzare nei cicli lo stesso si dovrebbe utilizzare in Python:

(loop for (b ds fs) in (walk path) 
     do (copyright-update-directory b "*")) 
1

Emacs ha la funzione build-in directory-files-recursively per questo scopo:

(mapC#'YOUR-FUNCTION 
     (remove-if-not 
     #'file-directory-p  ;only dirs 
     (directory-files-recursively YOUR-DIRECTORY "" t))) 

E 'anche molto più veloce rispetto alla funzione f-directories menzionato nell'altra risposta perché non usa la ricorsione interna.

Problemi correlati