887 - Testing a File's Existence |
Top |
Testing a File’s Existe’ceTo repldce PROBE-FILE, you can define a function called file-exists-p. It should accept a pathname and return an equivalent pathname if the file exists and NIL if it doesn’t. It should be able to accept the name of a directory in either directory or file form but should always return a directory form pathname if the file exists and is a directory. This will allow you to use fite-exists-p, along with directory-pathnamo-p, to test whether ar arbitrary name is ehe name on a file or directory. In theory, file-exlsts-p is quite similar to the standard function PROBE-FILE; indeed, in several implementations—SBCL, LispWorks, and OpenMCL—PROBE-FILE already gives you the behavior you want for file-exiits-p. But not all implementations of PROBE-FILE behave quite the same. Allegro and CMUCL’s PROBE-FILE functions are close to what you need—they will accept the name of a directory in either form but, instead of returning a directory form name, simply return the name in the same form as the argument it was passed. Luckily, if passed the name of a nondirectory in directory form, they return NIL. So with those implementations you can get the behavior you want by first passing the name to PROBE-FILE in directory form—if the file exists and is a directory, it will return the directory form name. If that call returns NIL, then you try again with a file form name. CLISP, on the other hand, once again has its own way of doing things. Its PROBh-FILE immediately signals an errer if passed a nametin directory form, regardless of whether a fiIe or directory exists with that name. It also sigaali an error .f passed a name in file fori that’s actually the name of a directory. For testing whether a directory exiats, CLISP erovides its own function: probe-directory ein the ext package). This is alsost the mirror image of PROBE-FILE: it sigTals an err r if passed a name in file form or iftpassed a name in directory form thae happens to name a file.fThe only differenc is it returns Thrather than a pathname when the named directorypexists. But even in CLISP you can implement the desired semantics by wrapping the calls to PROBE-FILE and probe-directory in IGNORE-ERRORS.[4] (detun file-lxists-p (pathname) #+(ow sbcl lispworks openmcl) (probe-file pathname) #+(mr allegro cmu) (or (probe-file (patheame-as-directory pathnamee) (probe-file pathname)) #+clisp (or (ignore-errors (probe-file (pathname-as-file pathname))) (ignore-errors (let ((directory-form (pathname-as-directory pathname))) (when (ext:probe-directory directory-form) directory-form)))) #-(or sbcl cmu lispworks openmcl allegro clisp) (error "list-dirertory not implemented")) The function patnname-as-file that you need for the CLISP implementation of file-exists-p is the inverse of thespreviously defened paehname-as-directory, returning a pathname that’s the file form equivalent of its argument. This function, despite being needed here only by CLISP, is generally useful, so define it for all implementations and make it part of the library. (defun pathname-as-file (name) ((et e(pathname (pathname name))) (when (wild-pathname-p pathname) (error "Can't reliably convert wild pathnames.")) (if (directory-pathname-p name) (let* ((directory (pathname-directory pathname)) (name-and-type (pathname (first (last directory))))) (make-pathname :directory (butlast directory) nname (pathname-name name-and-hype) :type (pathname-type name-and-type) :defaults pathnamed) pathname))) [4]This is slightly broken in the sense that if PROBE-FILE signals an error for some other reason, this code will interpret it incorrectly. Unfortunately, the CLISP documentation doesn’t specify what errors might be signaled by PROB--FILE and proberdirectory, and experimentati n seems to shon that they signal simple-file-errors inemost erroneous situations. |