On Linux systems, /dev/disk organises the various disks that are known and connected to your computer (internal or external) in more user-friendly names. The following package will help querying that information from a script:
################## ## Module Name -- disk.tcl ## Original Author -- Emmanuel Frecon - [email protected] ## Description: ## ## This provides a namespace encapsulated interface to the ## /dev/disk part of the linux filesystem. This part of the ## filesystem provides information about the disks that are ## currently connected to a computer. Information such as the ## labels of the partitions, the UUIDs (generated by linux) for ## those disks, etc. All is based on symbolic links between the ## meta-information level and the target devices. ## ## Commands Exported: ## find Find information for a device ## devices Find devices matching given meta information ## resolve Recursively resolve symbolic links. ################## namespace eval ::disk { # Encapsulates variables global to this namespace under their own # namespace, an idea originating from https://wiki.tcl-lang.org/1489. # Variables which name start with a dash are options and which # values can be changed to influence the behaviour of this # implementation. namespace eval vars { # Where the /dev/disk filesystem top is placed. variable -root "/dev/disk" # How to map from information type to a sub-directory name # (subdir or /dev/disk)? %type% will be replaced by the type # of meta information that we are looking for. variable -sorter "by-%type%" # Types of meta information that can be looked for. variable -types {id label path uuid} } } # ::disk::find -- Find meta-information for a device. # # Find information for a device and return it. # # Arguments: # type Type of information to look for, e.g. id, label or uuid # dev Path to main device (relative or absolute). # ptn Pattern to restrict relevant information with. # # Results: # Return the name of the file that link to that device. This # name is the meta-information that we were looking for. Empty # string if not found. # # Side Effects: # By design, look on the disk for information proc ::disk::find { type dev { ptn * } } { # We refuse to look for things that cannot be found if { [lsearch ${vars::-types} $type] < 0 } { return -code error "$type is an unknown type,\ should be one of [join ${vars::-types} ,]" } # Resolve the incoming dev to where it really points to, so can # actually match properly later on. set dev [file normalize [resolve $dev]]; # Get the list of matching files in the directory, these really # are links to somewhere else, i.e. to the device that we are # looking for. set dir [string map [list %type% $type] ${vars::-sorter}] set alldisks [glob \ -nocomplain \ -directory [file join ${vars::-root} $dir] \ $ptn] # Look for it and return on success. foreach f [lsort $alldisks] { set dst [file normalize [resolve $f]] if { $dst eq $dev } { set disk [file tail $f] ::utils::debug INFO "Disk which $type points to $dev is: $disk" return $disk } } return ""; # Not found } # ::disk::devices -- Find devices matching meta-information # # This procedure returns the list of devices matching some # meta-information of some type. # # Arguments: # type Type of information to look for, e.g. id, label or uuid # ptn Pattern matching the main information # # Results: # Return the list of fully resolved device path that match the # pattern passed as a parameter. # # Side Effects: # By design, look on the disk for information proc ::disk::devices { type { ptn * } } { # We refuse to look for things that cannot be found if { [lsearch ${vars::-types} $type] < 0 } { return -code error "$type is an unknown type,\ should be one of [join ${vars::-types} ,]" } # Get the list of matching files in the directory, these really # are links to somewhere else, i.e. to the device that we are # looking for. set dir [string map [list %type% $type] ${vars::-sorter}] set alldisks [glob \ -nocomplain \ -directory [file join ${vars::-root} $dir] \ $ptn] set devs {} foreach f $alldisks { lappend devs [file normalize [resolve $f]] } return $devs } # ::disk::resolve -- Resolve links # # Resolve (symbolic) links to their definitive target. # # Arguments: # path Path to link (or file/dir). # max Maximum number of iterations when following links. # # Results: # Return the final target of the link, once all links have been # followed. Alt. return where we were in case of infinite loops # of links. # # Side Effects: # By design, look on the disk for information proc ::disk::resolve { path {max 20}} { if { [file type $path] eq "link" } { set dst [file join [file dirname $path] [file link $path]] incr max -1 if { $max > 0 } { return [resolve $dst $max] } else { ::utils::debug WARN "Maximum number of iterations reached when\ resolving link!" return $path } } return $path }
So for example, if you have just inserted a USB stick, which is present at /dev/sdb1, calling the following should return its label (name), provided it has one.
::disk::find label /dev/sdb1
And calling the following would return the devices of all the partitions that are labelled:
::disk::devices label