file mkdir

file mkdir creates directories.

See Also

TIP #431 Discussion
The implications of file mkdir not surfacing an EEXIST error to the script level.

Synopsis

file mkdir dir ?dir ...?

Description

file mkdir ensures that the directories named by the dir arguments exist, creating them if necessary and also creating as necessary any pathname components of each dir. It is an error for any dir argument to be the name of an existing file that is not a directory. If an error occurs for some dir argument, no subsequent dir arguments are processed.

Discussion

Csan: When and how would it be possible to rewrite the following code into pure and simple Tcl while keeping the atomicity of the Unix mkdir?:

set unid $A
while {[catch {exec mkdir uniqueids/$unid}]} {
    if {[incr unid] > $B} {set unid $A}
} 
puts "$unid is available and has been locked."

The problem the above code is a solution for is: "Select the first available id between $A and $B. 'Available' is defined as 'not used by others'. When found, make sure you also lock it. When not used any more, unlock it."

The best Tcl solution for the problem would be to have negative feedback when trying to create an already existing directory. E.g.:

file mkdir -booleanresult uniqueids/$unid

(or similar) which returned a boolean value depending on the success or failure of the directory creation would be a very good (best) improvement over the original code above. (Note that '-booleanresult' is only one of the possible names for the switch).

US: Unfortunately the code above does not work (see second sentence on this page). Dunno why. Maybe some obscure conformance to Windoze behaviour.

RS: How about this variation?

# Assumptions:
# A contains an integer value representing the low end of a range
# B contains an integer value representing the high end of a range
# Code rotates between A and B, looking for a directory that does not currently exist

set unid $A
while {[file exists uniqueids/$unid]} {
    if {[incr unid]>$B} {set unid $A}
}
file mkdir uniqueids/$unid
puts "$unid is available and has been locked."

Csan: the variation is perfect code but not good for the purpose since the check and the creation is not happening at the same time (in other words they are not atomic: there is a time frame between the check and the creation of the directories when other similar code could interfere). E.g. how would you deal with concurrent processes or in case there is a (very) high I/O load which in turn causes several of this code to be enqueued? I don't feel like we get 100% unique ids (unique in the sense that there are not used by other processes).


Csan the perfect Tcl equivalent hint was provided by KBK (thank you!): open has an EXCL option. From open(3tcl): EXCL: "If CREAT is also specified, an error is returned if the file already exists."

So instead of

while {[catch {exec mkdir $uidd}]} {}

the following pure TCL can be used which provides the same functionality:

while {[catch {close [open $uidd {RDWR CREAT EXCL}]}]} {}

pyk 2012-11-11: Not the same, the first creates a directory, the second creates a file.