MakeUniqueFilenameNumber
Function MakeUniqueFilenameNumber( const aFilename : string) : string
Example
procedure ScriptEvent(var Value: variant);
begin
Value := MakeUniqueFilenameNumber('C:\Fictional\order.csv');
// If order.csv exists and order2.csv does not, returns order2.csv.
end;
Usage
MakeUniqueFilenameNumber returns the original file name when absent or the first currently unused numeric-suffixed alternative starting at 2.
Parameters
| Name | Type | Description |
|---|---|---|
aFilename | string, const | Preferred path/name. Relative paths are queried from the process current directory. |
Returns
The original string when currently absent; otherwise <path><base>2<extension>, <path><base>3<extension>, and so on until a currently absent candidate is found. No separator is inserted before the number.
Behaviour
- Existing
order.csvfirst proposesorder2.csv, notorder1.csvororder_2.csv. - If
order2.csvandorder3.csvexist, the next proposal isorder4.csv. - An absent preferred path is returned exactly.
- Only the final extension is preserved separately.
Errors
File-existence checks can be affected by access restrictions and files being created or removed concurrently. String allocation, counter overflow and other unexpected errors are raised to the script.
Usage notes
Use when human-readable sequential alternatives are preferred and collision races are handled by the later file-creation operation. Use GUID suffixes when avoiding long sequential scans matters.
Additional Technical Info
MakeUniqueFilenameNumber returns aFilename unchanged when it does not currently identify a file. When it exists, the function tests numeric suffixes beginning at 2 and returns the first candidate for which FileExists is false.
The example uses a fictional path and was not executed by the documentation workflow. The returned path is not created or reserved.
Implementation
After an initial FileExists, the Velox implementation splits the path/name/final extension. It removes the extension from the base, sets an Integer counter to 2, builds lPath + lFilename + IntToStr(i) + lExt, increments the counter, and repeats while the candidate exists.
Edge cases and quirks
- The result is not atomically reserved. Concurrent callers can receive the same candidate.
- Existing digits are not parsed: existing
order9.csvfirst proposesorder92.csv. - A dotfile
.envhas an empty base and first proposes2.env. - A directory at the preferred path makes
FileExistsfalse, so the unchanged directory path is returned. - Dense existing numeric sequences cause many synchronous metadata queries, especially expensive on remote storage.
- In the theoretical case of exhausting
Integer, current checked arithmetic can raise rather than return a name. - No sanitisation, path-length validation or permission/access proof is performed.
Side effects
No persistent change. It performs one or more file-system existence queries.
Performance and concurrency
Cost is linear in the number of occupied candidates, with one file-system query per candidate. There is no locking or atomic create, so it is unsafe as a concurrency allocator.
Related entries
MakeUniqueFilenameuses a GUID suffix after one occupied preferred name.AppendIdFilenamealways inserts a GUID without checking storage.FileExistsdefines the query semantics and race boundary.
External references
- Embarcadero
System.SysUtils.FileExists - Free Pascal
FileExists- compatible query context; the starting value and concatenation sequence are Velox-owned.