common-lispsbcluiop

How to provide a correct path when using run-program


For example, I have a bunch of files name like this:

[foo

And I'm writing some code to collect and do some process to them.

(setf a (car (uiop:directory-files "/path/to/dir")));;for simplicity
                                              ;;we suppose there is only a [foo at /path/to/dir
(uiop:run-program (list "cat" (namestring a)));; cat is just an example

then it says this:

 Subprocess #<UIOP/LAUNCH-PROGRAM::PROCESS-INFO {1009C93CA3}>
 with command ("cat" "/path/to/dir/\\[foo")
 exited with error code 1

while (uiop:run-program (list "cat" "/path/to/dir/\[asd")) looks good.

I have also tried something like this:

(format NIL "~A" a)
(format NIL "~S" temp)
(princ-to-string temp)

So How can I call run-program with a rigth pathname?


Solution

  • The truename is printed readably for SBCL, and SBCL allows brackets in their pathnames as wildcards so it needs to escape them in the printed representation. For example:

    #P"d[0-9]"
    

    has a pathname-name that is:

    #<SB-IMPL::PATTERN "d" (:CHARACTER-SET . "0-9")>
    

    When I test your example and inspect then pathname, I see:

    A pathname.                                                                                                                                                                                                                                                             
    Namestring: "/tmp/\\[a"                                                                                                                                                                                                                                                 
    Host: #<SB-IMPL::UNIX-HOST {100010D983}>                                                                                                                                                                                                                                
    Device: NIL                                                                                                                                                                                                                                                             
    Directory: (:ABSOLUTE "tmp")                                                                                                                                                                                                                                            
    Name: "[a"                                                                                                                                                                                                                                                              
    Type: NIL                                                                                                                                                                                                                                                               
    Version: :NEWEST                                                                                                                                                                                                                                                        
    Truename: #P"/tmp/\\[a"   
    

    So, the components are ok: the pathname name does not contain a bracket, but the pathname needs to be printed with a bracket in order to be readable.

    There is no requirements for pathnames to be printed in a way that works directly as a native filename, but there is a native filename interface in SBCL, documented here.

    Or, you can call (uiop:unix-namestring file).