REBOL [
    title: "Recurse Functions"
    author: "Christopher Ross-Gill"
    home: http://www.ross-gill.com/
    date: 7-Mar-2002
    version: 1.1.0
    file: %recurse.r
    purpose: "Provides a couple of recurse functions"
    usage: {
        recurse-list %./
        files: recurse-read %documents/
        write %files.xml recurse-xml %photos/
        recurse-delete %trash/
    }
]

ctx-recurse: context [

out: []
xml: ""

set 'recurse-list func [
    {
    Prints a structured list of all files and sub-directories of
    provided folder.
    }
    dir [file! url!]
    "The base-level directory (works for ftp too!)"
    /indent ind [string!]
    "Indent (used internally)"
    /local files [block!]
    "Files (used internally)"
][
    dir: dirize dir
    if not indent [ind: copy ""]
    files: sort read dir
    if (length? files) = 0 [print ind]
    foreach file files [
        either dir? join dir file [
            print [ind file]
            recurse-list/indent join dir file append copy ind "----"
        ][
            print [ind file]
        ]
    ]
]

set 'recurse-xml func [
    {
    Prints a structured list of all files and sub-directories of
    provided folder.
    }
    dir [file! url!]
    "The base-level directory (works for ftp too!)"
    /sub
    /indent ind [string!]
    "Indent (used internally)"
    /local files [block!]
    "Files (used internally)"
][
    dir: dirize dir
    if not indent [ind: copy ""]
    if not sub [
        xml: copy {<?xml version="1.0" encoding="iso-8859-1"?>}
        repend xml [newline build-tag reduce ['files 'path dir]]
    ]
    files: sort read dir
    foreach file files [
        either dir? join dir file [
            repend xml [
                newline ind
                build-tag reduce [
                    'folder
                    'name file
                    'path dir
                    'modified modified? join dir file
                ]
            ]
            recurse-xml/sub/indent join dir file append copy ind " "
            repend xml [newline ind </folder>]
        ][
            repend xml [
                newline ind
                build-tag reduce [
                    'file
                    'name file
                    'path dir
                    'modified modified? join dir file
                    'size size? join dir file
                    to-word "/"
                ]
            ]
        ]
    ]
    if not sub [return repend xml [newline </files>]]
]

set 'recurse-read func [
    {
    Like 'read only includes sub-directories.
    Files include path information.
    }
    dir [file! url!]
    "The base-level directory (works for ftp too!)"
    /sub
    /local
    files [block!]
    "Files (used internally)"
][
    if not sub [out: copy []]
    dir: dirize dir
    files: sort read dir
    foreach file files [
        repend out [join dir file]
        if dir? join dir file [
            recurse-read/sub join dir file
        ]
    ]
    if not sub [return out]
]

set 'recurse-delete func [
    {
    Deletes a directory including all sub-directories and contents.
    }
    dir [file! url!]
    "The base-level directory (works for ftp too!)"
    /indent ind [string!]
    "Indent (used internally)"
    /local files [block!]
    "Files (used internally)"
][
    dir: dirize dir
    if not indent [ind: copy ""]
    files: sort read dir
    if (length? files) = 0 [print ind]
    foreach file files [
        print [ind file]
        if dir? join dir file [
            recurse-delete/indent join dir file append copy ind "----"
        ]
        delete join dir file
    ]
]

]

if not system/script/args [halt]