deleteing a folder and everything contained in it

Started by SHX, May 18, 2007, 11:50:54 AM

Previous topic - Next topic

SHX

Here is a piece of code that i started working on to get the files in a folder
(define (getfilesinfolder z) ( map  (fn (a) (append z a ) )(replace ".." (replace "." (clean (fn (x) (directory? (append  z x)))  (directory z))))) )

Fisrt of all is this a good way of doing it?



Also, my real goal is to delete all the folders/ subfolders and files that are in a parent folder including the parent folder as well.



So I would like to set up a function that does this.



Can anyone help?



Steven

cormullion

#1
Perhaps this sort of thing. Untested - replace the innocent println statements with your own brand of destructive mayhem...


(define (delete-disk-item di)
  (if (directory? di)
    (println "delete directory" di)
    (println "delete file" di)))

(define (walk-tree dir)
  (dolist (di (directory dir {^[^.]}))
  (if (directory? (append dir "/" di))
      (walk-tree (append dir "/" di )))
  (delete-disk-item (append dir "/" di))))

(walk-tree f)
(delete-disk-item f)


Edit - I don't think that works. Sorry - don't have time to find out why.. :-(

Sleeper

#2
Hi, SHX!

try this function:



(define (remove-all dir)
    (set 'fnames (list dir))
    (set 'dirs '())

    (while (not (empty? fnames))
        (set 'fname (pop fnames))
        (if (directory? fname)
            (begin
                (dolist (x (directory fname))
                    (if (and (!= x ".") (!= x ".."))
                        (push (append fname "/" x) fnames)))
                (if (!= fname dir) (push fname dirs)))
            (delete-file fname)))

    (dolist (x dirs) (remove-dir x)))


it removes all files and subdirs in directory.

i tested it on windows xp only



edit: to remove root folder as well replace

  (if (!= fname dir) (push fname dirs))

with just

  (push fname dirs)

Sleeper

#3
this recursive version is better

i forgot about it :)



(define (remove-all root, x full)
    (dolist (x (directory root))
        (set 'full (append root "/" x))
        (if (directory? full)
            (if (and (!= x "..") (!= x "."))
                (begin
                    (remove-all full)
                    (remove-dir full)))
            (delete-file full))))


example:


(remove-all "c:\temp")
(remove-dir "c:\temp")

SHX

#4
Sleeper,



Thank you for a very elegant  solution.



Also, being that I am new to newlisp, this was a very good learning experience.



One question,



(define (remove-all root, x full)



Is "X" and "full" are put in the define statement to make them private variables?



Steven

Sleeper

#5
I put "x" and "full" in define statement to make them local to this function.



http://newlisp.org/CodePatterns.html#locals">//http://newlisp.org/CodePatterns.html#locals



Also in this case they don't pollute global namespace. In recursive functions non-local variables may cause big problems, as they are shared between all running functions.

cormullion

#6
I think that comma is cool... :-)


(define (remove-all root, x full)
  (println root)
  (println ,)
  (println x)
  (println full))
 
(remove-all 1 2 3 4)
1
2
3
4

(println root)
(println ,)
(println x)
(println full)

nil
nil
nil
nil


Sleeper

#7
i totally agree ;D

rickyboy

#8
Quote from: "Sleeper"this recursive version is better

...

Yes!  This problem screams for a recursive solution.  For those about to recurse, I salute you!  :-)



BTW, you don't have to shadow the variable x by way of your function's parameter list, as x is already locally scoped by the dolist.



Also, the body of your function looks like a framework for a nice abstraction; remove-all can be an instance of that abstraction:
(define (walk-dir ffunc dfunc root)
  "Walk a directory tree at `root' and apply `dfunc' to
directories and `ffunc' to files."
  (dolist (x (directory root))
    (let (full (append root "/" x))
      (if (directory? full)
          (when (and (!= x "..") (!= x "."))
            (walk-dir ffunc dfunc full)
            (dfunc full))
        (ffunc full)))))

(define remove-all (currie walk-dir delete-file remove-dir))

Of course, you'll need the following handy macros.
(define-macro (when)
  (letex ($test (eval (args 0))
          $expr (cons 'begin (1 (args))))
    (if $test $expr)))

(define-macro (currie f)
  (letex ($f (eval f)
          $cargs (map eval (args)))
    (lambda () (apply $f (append (quote $cargs) (args))))))
(λx. x x) (λx. x x)

Sleeper

#9
you're right, i put x after comma just in case :)



good idea with currying, it may be useful

i used for different tasks similar recursive walk function (much like in python os.walk) but without curry.