deleteing a folder and everything contained in it

Machine-specific discussion
Unix, Linux, OS X, OS/2, Windows, ..?
Locked
SHX
Posts: 37
Joined: Fri Feb 16, 2007 11:06 pm

deleteing a folder and everything contained in it

Post by SHX »

Here is a piece of code that i started working on to get the files in a folder

Code: Select all

(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
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Post by cormullion »

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

Code: Select all

(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
Posts: 24
Joined: Fri Nov 24, 2006 2:24 pm

Post by Sleeper »

Hi, SHX!
try this function:

Code: Select all

(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
Posts: 24
Joined: Fri Nov 24, 2006 2:24 pm

Post by Sleeper »

this recursive version is better
i forgot about it :)

Code: Select all

(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:

Code: Select all

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

SHX
Posts: 37
Joined: Fri Feb 16, 2007 11:06 pm

Post by SHX »

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
Posts: 24
Joined: Fri Nov 24, 2006 2:24 pm

Post by Sleeper »

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

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
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Post by cormullion »

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

Code: Select all

(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
Posts: 24
Joined: Fri Nov 24, 2006 2:24 pm

Post by Sleeper »

i totally agree ;D

rickyboy
Posts: 607
Joined: Fri Apr 08, 2005 7:13 pm
Location: Front Royal, Virginia

Post by rickyboy »

Sleeper wrote: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:

Code: Select all

(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.

Code: Select all

(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
Posts: 24
Joined: Fri Nov 24, 2006 2:24 pm

Post by Sleeper »

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.

Locked