user13476485
user13476485

Reputation:

Is it possible to capture the error output of glob?

Suppose if I have the following glob command wrapped in try/trap/finally:

proc generateSubmissionFolder {cover_letter_resume submission_path} {
   set submission_parent [file dirname $submission_path]
   set latest_submission_folder [lindex [lsort [glob -directory $submission_parent -type d *]] end]
   set latest_submission_file [lindex [glob -directory $latest_submission_folder *[file extension $cover_letter_resume]] end]
   createSubmissionFolder $latest_submission_file $submission_path
}


proc createSubmissionFolder {source destination} {
    puts "Creating $destination folder."
    file mkdir $destination
    puts "Copying $source to $destination"
    file copy $source $destination
}


try {

    # I gathered user input and stored them in the variables $company_name and $position.

    set submission_path [file join $company_name $position $yearmonthday]

    if {[file exists [file dirname $submission_path]]} {
        generateSubmissionFolder $coverletterresume $submission_path
    } else {
        createSubmissionFolder $coverletterresume $submission_path
    } 

} trap {Value Empty} {errormessage} {
   puts "$errormessage"
} finally {
   puts "$argv0 exiting."
}

If no folder is found, I would like to provide a human readable error message, but I'm unsure of what error to trap. According to the answer to my previous question:

Tcl doesn't have a pre-defined hierarchy of exceptions.

The only work around I tried was to use the -nocomplain switch and afterward check if the latest_submission_folder was blank.

Is there a way to trap a FileNotFound or FolderNotFound error?

Upvotes: 0

Views: 705

Answers (2)

Donal Fellows
Donal Fellows

Reputation: 137767

In this specific case, glob has an option that helps: -nocomplain. It turns off the error on no match — which was only ever really intended for interactive use — as a lot of use cases can cope with an empty returned list just fine. (It's the way it is for historical reasons, and is maintained that way so we don't break the large number of existing scripts that use it. As language warts go, it's not too terrible.)

set latest_submission_folder [glob -directory $submission_parent -type d *]
if {![llength $latest_submission_folder]} {
    # Make your own handling right here. Whatever you want.
    puts "I didn't find a directory inside $submission_parent"
} elseif {[llength $latest_submission_folder] > 1} {
    # Many subdirectories found. Is this an error given your single-thing var name?
} else {
    # Strip a layer of list; good idea in case directory name has a space in it!
    set latest_submission_folder [lindex $latest_submission_folder 0]
}

Upvotes: 1

Shawn
Shawn

Reputation: 52579

For trivial cases like your example, use an on error handler, not trap. Or use catch instead of try.

Example tclsh session:

% try { glob *.bar } on error {what} { puts "Ooops: $what" }
Ooops: no files matched glob pattern "*.bar"
% if {[catch { glob *.bar } result] == 1} { puts "Ooops: $result" }
Ooops: no files matched glob pattern "*.bar"

Or if you do want to use trap because you also want to handle a bunch of other possible specific errors from more complicated code, glob raises a TCL OPERATION GLOB NOMATCH on failure:

% try { glob *.bar } trap {TCL OPERATION GLOB NOMATCH} {msg} { puts "Ooops: $msg" }
Ooops: no files matched glob pattern "*.bar"

You can discover what to use with trap for any given command's particular error with something like:

% catch { glob *.bar } result errdict
1
% dict get $errdict -errorcode
TCL OPERATION GLOB NOMATCH

Upvotes: 2

Related Questions