jima 2014-01-27
I paste here the proc (
GetFilePaths) I have to generate listings of files (following possibly a pattern) and folders given some starting folder.
This proc uses another auxiliary one (
MakeRelative) in the cases full paths are not needed but relative ones.
I reckon the names given to possible options and their possible values are perhaps unfortunate because of the hyphens.
# Proc GetFilePaths.
# Arguments.
# filePath The starting file path to operate on.
# -expected An option list with expected results.
# Possible value -expectedFiles.
# Possible value -expectedFolders.
# Defaults to {-expectedFiles -expectedFolders}.
# pattern Pattern to use only for files.
# Defaults to *.
# -makeRelative An option to tail the fPaths.
# Possible value -makeRelativeYes.
# Possible value -makeRelativeNo.
# Defaults to -makeRelativeNo.
# -recursive An internal flag to signal that is a recursive call.
# It is mostly used internally.
# Defaults to "" when invoked by the user.
# Internally it allows to pass the initial filePath.
# The user can pass -recursiveNo to avoid recursion.
#
# Returns.
# The list of files and folders suitable for ordered file deleting.
# If -makeRelativeYes then:
# Files and folders of the list are relative to filePath.
proc GetFilePaths {
filePath
{-expected {-expectedFiles -expectedFolders}}
{pattern *}
{-makeRelative -makeRelativeNo}
{-recursive ""}
} {
# Prepare the list for this invokation.
set result ""
# Deal with each folder at filePath level.
# Only if recurse is allowed.
if {${-recursive} ne "-recursiveNo"} {
foreach folder [glob -nocomplain -type d -dir $filePath *] {
# Recurse.
if {${-recursive} eq ""} {
lappend result {*}[GetFilePaths \
$folder ${-expected} $pattern ${-makeRelative} $filePath
]
} else {
lappend result {*}[GetFilePaths \
$folder ${-expected} $pattern ${-makeRelative} ${-recursive}
]
}
# If files are needed, process each folder to get them.
if {"-expectedFiles" in ${-expected}} {
foreach file [glob -nocomplain -type f -dir $folder $pattern] {
# Make relative if needed.
if {${-makeRelative} eq "-makeRelativeYes"} {
lappend result [
MakeRelative $filePath $file ${-recursive}
]
} else {
lappend result $file
}
}
}
# If folders are needed, append them to the result list.
# This is done after files are added.
# To provide results in an order that suits rm command.
if {"-expectedFolders" in ${-expected}} {
# Make relative if needed.
if {${-makeRelative} eq "-makeRelativeYes"} {
lappend result [
MakeRelative $filePath $folder ${-recursive}
]
} else {
lappend result $folder
}
}
};# Each folder.
};# Folders at filePath level if not -recurseNo.
# Do not forget to process files at top level if they are needed.
if {
(
(${-recursive} eq "") ||
(${-recursive} eq "-recursiveNo")
) && ("-expectedFiles" in ${-expected})
} {
foreach file [glob -nocomplain -type f -dir $filePath $pattern] {
# Make relative if needed.
if {${-makeRelative} eq "-makeRelativeYes"} {
lappend result [MakeRelative $filePath $file ${-recursive}]
} else {
lappend result $file
}
}
}
# Do not forget to process folders at top level if they are needed.
if {
(${-recursive} eq "-recursiveNo") &&
("-expectedFolders" in ${-expected})
} {
foreach file [glob -nocomplain -type d -dir $filePath $pattern] {
# Make relative if needed.
if {${-makeRelative} eq "-makeRelativeYes"} {
lappend result [MakeRelative $filePath $file ${-recursive}]
} else {
lappend result $file
}
}
}
# Return the list with results.
return $result
}; # Proc GetFilePaths.
# Proc MakeRelative.
# When calling this externally do not set -recursive argument.
proc MakeRelative {filePath file {-recursive ""}} {
set result {}
if {${-recursive} eq "" || ${-recursive} eq "-recursiveNo"} {
set prefix $filePath
} else {
set prefix ${-recursive}
}
set first [string first $prefix/ $file]
if {$first == -1} {
set result $file
} else {
set result [string range $file [string length $prefix/] end]
}
return $result
};# Proc MakeRelative.
Some examples:
Get all files and folders that hang from a given folder.
set filesAndFolders [GetFilePaths $folder]
Get all files (but not folders) that hang from localFolder and follow the pattern *.IN.
set inFiles [GetFilePaths $localFolder -expectedFiles *.IN]