file-utility File rename utility

Welcome to the file rename utility

Purpose

This utility renames all files of a given directory so that the last modified date of each individual file is added as prefix at the very beginning of the filename.

The program is coded in Tcl/Tk and compiled to an executable so that it can be used “out of the box” and without the need to install something extra.

Example:

current_directory:
------------------

	demo01.txt  --> 20-03-01_demo01.txt
	demo02.txt  --> 20-03-02_demo01.txt
	demo03.txt  --> 20-03-03_demo01.txt
	                |-------|
	                |
	                | **date prefix** added by the filerename
	                | utility according to the last modified date
	                | of each individual file

Once files are renamed this way, the filename can be used to specify sort order (instead of sorting by date). The sort order keeps the same throughout the lifetime of a file, regardless if the modification time-stamp might change in the future.

Usage

Under windows you can either use the command dialog window to start “filerenamer” executable with one argument specifying a directory or: just use file explorer to drag and drop a directory onto the “filerenamer.exe” icon (my preferred option)!

  • Files in the directory which already have the date prefix in the name, are skipped and won’t get renamed a 2nd time.

  • Spaces in filenames are automatically converted to dash char’s.

Source code

# file rename utility
# set dir [file dirname [info script]]
# show console (under windows only)

catch {
	package require Tk
	wm withdraw .
	console show
	console eval {wm protocol . WM_DELETE_WINDOW {exit 0}}
	
	puts \
"
Welcome to the file rename utility v0.1
---------------------------------------

Purpose:

	This utility renames all files of a given directory
	so that the last modified date of each individual file
	is added at the very beginning of the filename.

	Once files are renamed this way, they can be sorted
	(same as sort by date) and the sort order keeps the same
	throughout the lifetime of a file, regardless
	if the modification time might change or not.

	Files in the directory which already have the date prefix
	in the name, are skipped and won't get renamed a 2nd time.
	
	Spaces in filenames are automatically converted to dash char's.

Usage:

	Under windows you can either use the command dialog window
	to start filerenamer executable with one argument
	specifying a directory or
	just drag and drop a directory onto the filerenamer icon!
	     -------------

Copyright:

	(c) 2020, Johann Oberdorfer - Engineering Support | CAD | Software
		johann.oberdorfer \[at\] gmail <dot> com
		www.johann-oberdorfer.eu

	This source file is distributed under the BSD license.
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
	See the BSD License for more details.
"
}

# https://wiki.tcl-lang.org/page/Time+and+date+validator
# "5:13:52" (%T) => 1
# "1/2/2003" (%D) => 1

proc timevalidate {format str} {
	# Start with a simple check: If the string cannot be parsed against
	# the specified format at all it's definitely wrong
	if {[catch {clock scan $str -format $format} time]} {
		return 0
	}
	
	# Create a table for translating the supported clock format specifiers
	# to scan format specifications
	set map {%a %3s %A %s %b %3s %B %s %d %2d %D %2d/%2d/%4d
		%e %2d %g %2d %G %4d %h %s %H %2d %I %2d %j %3d
		%J %d %k %2d %l %2d %m %2d %M %2d %N %2d %p %2s
		%P %2s %s %d %S %2d %t \t %T %2d:%2d:%2d %u %1d
		%V %2d %w %1d %W %2d %y %2d %Y %4d %z %4d %Z %s
	}
	
	# Build the scan format string out of the clock format string
	set scanfmt [string map $map $format]
	
	# Recreate the time string from the seconds value
	set tmp [clock format $time -format $format]
	
	# Scan both versions of the string representation
	set list1 [scan $str $scanfmt]
	set list2 [scan $tmp $scanfmt]
	
	# Compare all elements as numbers and strings
	foreach n1 $list1 n2 $list2 {
		if {$n1 != $n2 && ![string equal -nocase $n1 $n2]} {return 0}
	}
	
	# Declare the time string valid since all elements matched
	return 1
}


set current_dir [lindex $argv 0]
# set current_dir "C:/_Projekte_SoftwareEntwicklung/12_TclTK_StarterPackage/filerename/test"

set DELIM "_"
set DATEFMT "%y-%m-%d"

if { ![file exists $current_dir] } {
	
	puts \
"
***Error:
	No argument given to function.
	Please specify a directory name and try again!
"
	
} else {
	
	set file_list [glob -nocomplain -type f [file join $current_dir "*"]]
	set tmp_list [list]
	
	foreach item $file_list {
		# puts "$item - [clock format [file mtime $item] -format $DATEFMT]"
		
		set fdir [file dirname $item]
		set fname [file tail $item]
		set mtime [clock format [file mtime $item] -format $DATEFMT]
		
		set fname [string trim [string map {" " "-"} $fname]]
		set new_filename "${mtime}${DELIM}${fname}"
		# puts $new_filename
		
		# check out, if the date prefix is already part of the filename:
		# yy-mm-dd
		set str [string range $fname 0 [expr {[string length $DATEFMT] -1}]]
		
		# puts "$str : [timevalidate $DATEFMT $str]"
		
		if {![timevalidate $DATEFMT $str]} {
			
			if {[catch {file rename $item [file join $fdir $new_filename]} errmsg] == 0} {
				lappend tmp_list $new_filename
			} else {
				puts $errmsg
			}
		}
	}
	
	if {[llength $tmp_list] == 0} {

		puts "No files renamed - nothing more to do.\n"
	
	} else {

		puts "Files renamed to:\n"
		
		foreach f [lsort -dictionary $tmp_list] {
			puts $f
		}
		
		puts \
"\nDone ([llength $tmp_list] / [llength $file_list]) file(s) successfully renamed."
	}
}

Download

The actual package can be downloaded directly from the link provided below.

  • The zip file includes the source code and as well a pre-compiled binary for windows.
  • The execute-able does not require any additional software or library to be installed.
File name:Size / byte:
filerename0.1.zip66197905
The software is free as air, free to use and free to modify.
The source code is distributed under the BSD license
and in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the BSD License for more details.

Future improvements

… would be:

  • a graphical dialog with drag&drop capability (like Markdown2Go dialog) which allows to rename not only files but also directories

  • possibility to remove the datum prefix

  • possibility to specify the format of the prefix

Similar function implemented with VBS (Visual Basic Script Language)

In situations, where here is no tclsh interpreter installed or it is not possible to download and/or start an executable due to security policies, here is an implementation of basically the same functionality but in plain vbs code.

' -------------------------------------------------------------------
' --- add-timestamp-for-all-files-in-a-folder.vbs
' -------------------------------------------------------------------
' -----------------------------------------------------------------------------
' (c) 2021, Johann Oberdorfer - Engineering Support | CAD | Software
'     johann.oberdorfer [at] gmail.com
'     www.johann-oberdorfer.eu
' -----------------------------------------------------------------------------
' This source file is distributed under the BSD license.
'   This program is distributed in the hope that it will be useful,
'   but WITHOUT ANY WARRANTY; without even the implied warranty of
'   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
'   See the BSD License for more details.
' -----------------------------------------------------------------------------
' Purpose:
'   VBS script to add a time stamp to all files of a given folder
'	files which already have a time stamp, are skipped
' -------------------------------------------------------------------
' Change history:
'   21-07-22, Johann, Initial release 
' -------------------------------------------------------------------

Const TITLE = "Add Timestamp Function"

' -----------------------
' drag and drop arguments
' -----------------------

Set objArgs = WScript.Arguments
' For i = 0 to objArgs.Count - 1: WScript.Echo objArgs(i): Next

For i = 0 to objArgs.Count - 1
	msg = msg + objArgs(i) + vbNewLine
Next

If (objArgs.Count = 0) Then
	MsgBox _
		"No arguments given to the function." _
	+	vbNewLine + vbNewLine _
	+	"Usage: Select a directory and drag&drop it onto the program's icon.", _
	+	vbInformation + vbOKOnly, TITLE + ", Information: "

	WScript.Quit
End If

Select Case MsgBox( _
				"The following arguments have been passed to the function:" _
			+	vbNewLine + vbNewLine _
			+	msg _
			+	vbNewLine _
			+	"Would you like to continue?", _
			vbInformation + vbOKCancel, TITLE + ", Question: ")
	Case 1: ' O.K. pressed
	Case 2: WScript.Quit
End Select

Function CreateTimestamp (date_str)
	mm = Month(date_str)
	dd = Day(date_str)
	yy = Right (Year(date_str), 2) ' only take 2 digits
	If Len(mm) < 2 Then mm = "0" & mm
	If Len(dd) < 2 Then dd = "0" & dd

	CreateTimestamp = yy & "-" & mm &"-"& dd
End Function

' --------------
' here we go ...
' --------------
Set fs = CreateObject("Scripting.FileSystemObject")

For i = 0 to objArgs.Count - 1

	folder_name = objArgs(i)

	Set dir = fs.GetFolder(folder_name)
	' timestamp = CreateTimestamp(Now())

	cnt = 0
	For Each f In dir.Files
		file_name = f.Name
		base_name = fs.GetBaseName(file_name)
		ext = fs.GetExtensionName(file_name)

		' timestamp = CreateTimestamp(f.DateCreated)
		timestamp = CreateTimestamp(f.DateLastModified)

		If (InStr(file_name, timestamp) = 0) Then
			f.Name = timestamp & "-" & base_name & "." & ext
			cnt = cnt + 1
		End If
	Next

	If (cnt = 0) Then
		MsgBox _
			"No Files renamed." + vbNewLine _
		+	"You might want to specify a different directory and try again.", _
		+	vbInformation + vbOKOnly, TITLE + ", Information: "
	Else
		MsgBox _
			CStr(cnt) + " File(s) successfully renamed." + vbNewLine _
		+	"You might want check the result or continue with another directory.", _
		+	vbInformation + vbOKOnly, TITLE + ", Information: "
	End If

Next

Copy & paste this code into a file, save it and use the explorer to drag and drop a directory onto the program’s file icon. Files are instantly renamed as described, so you would probably want to backup your data beforehand.