Walking a Directory Tree(遍历一个目录树)

Finally, to round out this library, you can implement a function called walk-directory. Unlike the functions defined previously, this function doesn't need to do much of anything to smooth over implementation differences; it just needs to use the functions you've already defined. However, it's quite handy, and you'll use it several times in subsequent chapters. It will take the name of a directory and a function and call the function on the pathnames of all the files under the directory, recursively. It will also take two keyword arguments: :directories and :test. When :directories is true, it will call the function on the pathnames of directories as well as regular files. The :test argument, if provided, specifies another function that's invoked on each pathname before the main function is; the main function will be called only if the test function returns true.

最后,为了完成这个库,你可以实现一个称为 walk-directory 的函数。与前面定义的那些函数不同,这个函数不需要做任何事情来消除实现间的区别,它只需要用到你已经定义的那些函数。尽管如此,该函数很有用,你将在后续几章里多次用到它。它接受一个目录的名字和一个函数,并在该目录下所有文件的路径名上递归地调用该函数。它还接受两个关键字参数: :directories:test。当 :directories 为真时,它将在所有目录的路径名和正规文件上调用该函数。如果有 :test 参数,它指定另一个函数,在调用主函数之前在每一个路径名上调用该函数,主 函数只有当测试参数返回真时才会被调用。:test 参数的默认值是一个总是返回真的函数,它是通过调用标准函数 CONSTANTLY 而生成的。

(defun walk-directory (dirname fn &key directories (test (constantly t)))
  (labels
      ((walk (name)
         (cond
           ((directory-pathname-p name)
            (when (and directories (funcall test name))
              (funcall fn name))
            (dolist (x (list-directory name)) (walk x)))
           ((funcall test name) (funcall fn name)))))
    (walk (pathname-as-directory dirname))))

Now you have a useful library of functions for dealing with pathnames. As I mentioned, these functions will come in handy in later chapters, particularly Chapters 23 and 27, where you'll use walk-directory to crawl through directory trees containing spam messages and MP3 files. But before we get to that, though, I need to talk about object orientation, the topic of the next two chapters.

现在你有了一个用于处理路径名的有用的函数库。正如我提到的那样,这些函数在后面的章节里将会很有用,尤其是第 23 章和第 27 章,在那里你将使用 walk-directory 在混合了垃圾信息和 MP3 文件的目录树中艰难前行,但在我们到达那里之前,我还需要在接下来的两章中谈论一下面向对象。