Guile Scheme library for common file operations.
Add extension.
Add replace-extension.
Remove outdated installation instructions.



You can also use your local clone with git send-email.


Library indented to facilitate working with files and directories (the file system in general). Initially inspired by f.el, it now resembles mostly useful functions I find myself needing from time to time when interacting with the file system.

This project is going through a rewrite at the moment, meant to clean the code and improve the user-facing API.


f.scm provides two Guile modules: (f ports) and (f).

  • (f): this contains functions that always get passed a path and open a new port for that path.
  • (f ports): this mirrors some functions from (f), receiving already opened ports instead of paths.

It is recommended to import those modules with a prefix so they don't overwrite each other and some top-level functions.

(use-modules ((f) #:prefix f:)
             ((f ports) #:prefix p:))

If you want to read only the first line of a file, you can use the read-line from (f). If you want to read the next line from an already opened port, use the read-line from (f ports).

NOTE: All the examples below assume you imported f with the f: prefix and f ports with the p: prefix.


#read-bytes path

Read binary data from path.

Return the binary data as a bytevector.

(f:read-bytes "path/to/file")

#read-text path

Read text from path.

Return the text as a string.

(f:read-text "path/to/file")

#read-line path

Read a single line of text from path.

Return the line as a string. It doesn't contain a newline character.

(f:read-line "path/to/file")

#read-lines path

Read all the lines of a file.

Returns the lines as a list of strings.

(f:read-lines "path/to/file")

#write-bytes path bytes #:key (append #f)

Write a bytevector to a file. Overwrite the contents if #:append is #f, otherwise append at the end.

(f:write-bytes "path/to/file" #vu8(1 2 3) #:append #t)

#write-text path text #:key (append #f)

Write a string to a file. Overwrite the contents if #:append is #f, otherwise append at the end.

(f:write-text "path/to/file" "I'm a string" #:append #t)

#write-line path text #:key (append #f)

Write string to a file and put a newline after it. Overwrite the contents if #:append is #f, otherwise append at the end.

(f:write-text "path/to/file" "I'm a string" #:append #t)

#write-lines path lines #:key (append #f)

Write multiple lines to a file. The lines parameter is a list of strings. Overwrite the contents if #:append is #f, otherwise append at the end.

(f:write-lines "path/to/file" '("first line" "second line"))

#mkdir path #:key (parents #f)

Create a new directory. Use #:parents #t to also create parent directories if they don't already exist.

(f:mkdir "f1/f2/f3" #:parents #t)

#ls #:optional (dir (getcwd)) #:key (hidden #f)

List the files in the directory dir. If dir is not specified, it default to the current directory. To also display hidden files, use #:hidden #t. Displaying hidden files omits . (current dir) and .. (parent dir).

(f:ls)             ;; list the files in the current directory
(f:ls "other-dir") ;; list the files in other-dir
(f:ls #:hidden #t) ;; list all the files in the current directory

#traverse path f #:key (files-only #f)

Walk a directory tree, applying the function f to every file and directory you meet. If you want to apply f only to files, use #:files-only #t.

;; Display every file and directory in your home dir
(f:traverse (string-append "/home/" (getlogin)) 
            (lambda (x)
              (display x)

#delete path #:optional (recursive #f)

Delete the file or directory specified by path. If path is a directory and contains stuff, set recursive to #t to delete it and all its contents.

;; Delete all your porn
(f:delete (string-append "/home/" (getlogin) "/homework") #t)

#copy src dest #:optional (recursive #f)

Copy something from src to dest.

(f:copy "music" "media/audio" #t)

#move oldname newname

Move oldname to newname. (The parameter naming is different from copy because this is just an alias for rename-file.)

(f:move "media/audio" "media/songs")


Send suggestions and patches with what you think is useful for this library to my public mailing list.

#What needs improving?

We currently need some path manipulation code (splitting, joining, extracting segments etc.). We don't want to use the file-names library, because we want just functions on strings, not complex objects, but it could prove useful as inspiration.


f.scm is licensed under the GNU GPLv3. See COPYING.