1
votes

I'm tying to use file-system-tree function from https://www.gnu.org/software/guile/manual/html_node/File-Tree-Walk.html#File-Tree-Walk. In combination with remove-statfrom the link it results in tree-like list structure, e.g. for

test/
├── dir1
├── dir2
│   ├── file2
│   └── file3
└── file1

we get ("test" (("dir2" ("file2" "file3")) "dir1" "file1"))

How to convert that list to list of all full paths? like this ("test/" "test/file1" "test/dir2" "test/dir2/file3" "test/dir2/file2" "test/dir1")

2
Welcome to stack overflow. You have to be more specific. What have you tried sofar? Where are you stuck? Please read How to Ask and revise your question. - Johan

2 Answers

0
votes

What we need to do is define a recursive function that iterates over the car of the cdr of a given list, appending the car of the list to string items, and calling itself on another list element, then taking the returned items and appending the car of the list on those, too. Here's what that would look like in code:

(define (tree->full-path-list tree)
  (flatten (append (list (car tree))
                   (map (lambda (x)
                          (if (list? x)
                              (map (lambda (y)
                                     (string-append (car tree) "/" y))
                                   (tree->full-path-list x))
                              (string-append (car tree) "/" x)))
                        (car (cdr tree))))))

Hope that helps!

0
votes

I'm late to the party but I think this could be done in a much easier (and probably faster) way than the accepted solution, using a classical named-let:

(define (path-append part1 part2)
  ;; concatenate paths (lazy man's version)
  (if (non-empty-string? part1)
      (string-append part1 "/" part2)
      part2))

(define (f lst)
  (reverse 
   (let loop ((lst lst) (path "") (res null))
     (if (null? lst)
         res
         (let ((c (car lst)))
           (loop (cdr lst)
                 path
                 (if (list? c)
                     (loop c (car res) res) ; this recurses into sub-lists
                     (cons (path-append path c) res))))))))

Not perfect, but close:

> (f '("test" (("dir2" ("file2" "file3")) "dir1" "file1")))
'("test" "test/dir2" "test/dir2/file2" "test/dir2/file3" "test/dir1" "test/file1")