All file systems follow the same general naming conventions for an individual file: a base file name and an optional
extension, separated by a period. However, each file system, such as NTFS and FAT, can have specific and differing rules about the formation of the individual components in a
directory or file name. Character count limitations can also be different and can vary depending on the path name prefix format used. Any Windows (Win32) application developer should be aware of these limitations and differences and know which file and path names are valid.
For example, the older MS-DOS FAT file system supports a maximum of 8 characters for the base file name and 3 characters for the
extension, for a total of 12 characters including the dot separator. This is commonly known as an 8.3 file name. The Windows FAT and NTFS file systems are not
limited to 8.3 file names, because they have long file name support.
Be aware that the term directory simply refers to a special type of file as far as the file system is concerned, therefore in certain contexts some reference material will use the general term file to encompass both concepts of directories and data files as such. Because of the higher level nature of this topic, it will use the term file to refer to actual data files only.
Some file systems, such as NTFS, support linked files and directories, which also follow file naming conventions and rules just as a regular file or directory would. For additional information, see Hard Links and Junctions and Reparse Points and File Operations.
For additional information, see the following subsections:
Basic Naming Conventions
The following fundamental rules enable applications to create and process valid names for files and directories, regardless
of the file system:
- Use a period to separate the base file name from the extension in the name of a directory or file.
- Use a backslash (\) to separate the components of a path. The backslash divides the file name from the path to it, and
one directory name from another directory name in a path. For additional details about what a path is, see the Path Names and Namespaces section below.
- Use a backslash as required as part of volume names, for example,
the "C:\" in "C:\path\file" or the "\\server\share" in "\\server\share\path\file" for Universal Naming Convention (UNC) names. You cannot use a backslash in the actual file or directory name components because it separates the names into components.
- Use almost any character in the current code page for a name, including Unicode characters and characters in the extended character set (128–255), except for the following:
- The
following reserved characters are not allowed:
< > : " / \ | ? *
- Characters whose integer representations are in
the range from zero through 31 are not allowed.
- Any other character that the target file system does not allow.
- Use a period as a directory component in a path to represent the current directory, for example ".\tmp.txt".
- Use two consecutive periods (..) as a directory component in a path to represent the parent of the current
directory, for example "..\tmp.txt".
- Do not use the following reserved device names for the name of a file:
CON, PRN, AUX, NUL, COM1, COM2,
COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, and LPT9
Also avoid
these names followed immediately by an extension; for example, NUL.txt is not recommended.
- Do not assume case sensitivity. For example, consider the names OSCAR, Oscar, and oscar to be the same, even though some file systems (such as a POSIX-compliant file system) may consider them as different. Note that NTFS supports POSIX semantics for case sensitivity but this is not the default behavior. For additional information, see CreateFile.
- Do not end a file or directory name with a trailing space or a period. Although the underlying file
system may support such names, the operating system does not. However, it is acceptable to start a name with a period.
Path Names and Namespaces
The path to a specified file consists of one or more components, separated by special characters, with each component usually being a directory name or file name, with some notable exceptions discussed below. It is often critical to the system's interpretation of a path what the beginning of the path (the prefix) looks like and what special characters are used in which position within the path, including the last character. If a component of a path is a file name, it must be the last component.
Each component of a path will also be constrained by the maximum length specified for a particular file system. In general, these rules fall into two categories: short and long. Note that directory names are stored by the file system as a special type of file, but naming rules for files also apply to directory names. A path is simply the string representation of the hierarchy between all of the directories that exist for a particular file or directory name.
Any discussion of path names needs to include the concept of a namespace in Windows. There are two main categories of namespace conventions used in the Win32 APIs, commonly referred to as the NT namespace and the Win32 namespace. The NT namespace was designed to be the lowest level namespace on which other subsystems and namespaces could exist, including the Win32 subsystem and, by extension, the Win32 file and device namespaces. POSIX is another example of a subsystem in Windows that is built on top of the NT namespace. Early versions of Windows also defined several predefined, or reserved, names for certain special devices such as communications (serial and parallel) ports and the default display console as part of what is now called the NT device namespace, and are still supported in currect versions of Windows for backward compatibility.
To sort out some of this, the following items are different examples of Win32 namespace prefixing and conventions, and summarizes how they are used.
The "\\?\" prefix tells the Win32 APIs to disable all string parsing and to send this string straight to the file system. For example, if the file system supports large paths and file names, you can exceed the MAX_PATH limits that are otherwise enforced by the Win32 APIs. This also allows you to turn off automatic expansion of ".." and "." in the path names. Many but not all file APIs support "\\?\"; you should look at the reference topic for each API to be sure.
The "\\.\" prefix will access the device namespace instead of the file namespace. This is how you access physical disks and volumes directly, without going through the file system, if the API supports this type of access. You can access many other devices this way (using the CreateFile and DefineDosDevice functions, for example).
Most APIs won't support "\\.\", only those that are designed to work with the device namespace.
For example, if you want to open the system's serial communications port 1, you can use either "\\.\COM1" or "COM1" in the call to the CreateFile function. This works because COM1-COM9 are part of the reserved names in the NT file namespace as previously mentioned.
But if you have a 100 port serial expansion board and want to open COM56, you need to open it using "\\.\COM56". This works because "\\.\" goes to the device namespace, and there is no predefined NT namespace for COM56.
Another example of this is using the CreateFile function on "\\.\PhysicalDiskX" or "\\.\CdRom1" allow you to access those devices, bypassing the file system.
It just happens that the device driver that implements the name "C:\" has its own namespace that is the file system. APIs that go through the CreateFile function should work because CreateFile is the same API to open files and devices.
If you're working with Win32 functions, you should use only "\\.\" to access devices and not files.
There are also APIs that allow the use of the NT namespace convention, but the Windows Object Manager makes that unnecessary in most cases. To illustrate, it is useful to browse the Windows namespaces in the system object browser using the Windows Sysinternals WinObj tool. When you run this tool, what you see is the NT namespace rooted at "\". The subdirectory "Global??" is where the Win32 namespace resides.
Named device objects reside in the NT namespace within the "Device" subdirectory. Here you may also find Serial0 and Serial1, the device objects representing the two COM ports if present on your system. The device object representing a volume would be something like "HarddiskVolume1", although the numeric suffix may vary. The name "DR0" under subdirectory "Harddisk0" would be the device object representing a disk, and so on.
To make these device objects accessible by Win32 applications, the device drivers create a symbolic link (symlink) in the Win32 namespace to their respective device objects.
For example, COM0 and COM1 under the "Global??" subdirectory are simply symlinks to Serial0 and Serial1, "C:" is a symlink to HarddiskVolume1, "Physicaldrive0" is a symlink to DR0, and so on.
Without a symlink, a specified device "Xxx" will not be available to any Win32 application using Win32 namespace conventions as described previously. However, a handle could be opened to that device using any APIs that support the NT namespace absolute path of the format "\Device\Xxx".
With the addition of multi-user support via Terminal Services and virtual machines, it has further become necessary to virtualize the system-wide root device within the Win32 namespace. This was accomplished by adding the symlink named "GLOBALROOT" to the Win32 namespace, which you can see in the "Global??" subdirectory of the WinObj browser tool previously discussed, and can access via the path "\\?\GLOBALROOT". This prefix ensures that the path following it looks in the true root path of the system object manager and not a session-dependent path.
Maximum Path Length
In the Windows API (with some exceptions discussed in the following paragraphs), the maximum length for a path is MAX_PATH, which is
defined as 260 characters. A local path is structured in the following order: drive letter, colon, backslash, components
separated by backslashes, and a terminating null character. For example, the maximum path on drive D is
"D:\<some 256 character path string><NUL>" where "<NUL>" represents the invisible terminating null character for the current system codepage. (The characters < > are used here for visual clarity and cannot be part of a valid path string.)
Note File I/O functions in the Windows API convert "/" to "\" as part of converting the
name to an NT-style name, except when using the "\\?\" prefix as detailed in the following sections.
The Windows API has many functions that also have Unicode versions to permit an extended-length path for a maximum total path length of 32,767 characters.
This type of path is composed of components separated by backslashes, each up to the value returned in the lpMaximumComponentLength parameter of the GetVolumeInformation function. To specify an extended-length path, use the
"\\?\" prefix.
For example, "\\?\D:\<very long path>". (The characters < > are used here for visual clarity and cannot be part of a valid path string.)
Note The maximum path of 32,767 characters is approximate, because the "\\?\" prefix may be
expanded to a longer string by the system at run time, and this expansion applies to the total length.
The "\\?\" prefix can also be used with paths constructed according to the universal naming convention (UNC). To specify such a path using UNC, use the
"\\?\UNC\" prefix. For example, "\\?\UNC\server\share", where "server" is the name of the machine and "share" is the name of the shared folder. These
prefixes are not used as part of the path itself. They indicate that the path should be passed to the system with
minimal modification, which means that you cannot use forward slashes to represent path separators, or a period
to represent the current directory. Also, you cannot use the "\\?\" prefix with a relative path,
therefore relative paths are limited to MAX_PATH characters as previously stated for paths not using the "\\?\" prefix.
When using an API to create a directory, the specified path cannot be so long that you cannot append an
8.3 file name (that is, the directory name cannot exceed MAX_PATH minus 12).
The shell and the file system have different requirements. It is possible to create a path with the Windows API that
the shell user interface might not be able to handle.
Relative Paths
For functions that manipulate files, the file names can be relative to the current directory. A file name is
relative to the current directory if it does not begin with one of the following:
- A UNC name of any format.
- A disk designator with a backslash, for example "C:\".
- A backslash, for example, "\directory").
If the file name begins with a disk designator with a backslash, it is a fully qualified path (for example, "C:\tmp"). If a
file name begins with only a disk designator but not the backslash after the colon, it is interpreted as a relative path to the current directory on the drive with the
specified letter . Examples of this format are as follows:
- "C:tmp.txt" refers to a file in the current directory on drive C.
- "C:tempdir\tmp.txt" refers to a file in a subdirectory to the current directory on drive C.
A path is also said to be relative if it contains "double-dots"; that is, two periods together in one component of the path. This special specifier is used to denote the directory above the current directory, otherwise known as the "parent directory". Examples of this format are as follows:
- "..\tmp.txt" specifies a file named tmp.txt located in the parent of the current directory.
- "..\..\tmp.txt" specifies a file that is two directories above the current directory.
- "..\tempdir\tmp.txt" specifies a file named tmp.txt located in a directory named tempdir that is a peer directory to the current directory.
Relative paths can combine both example types, for example "C:..\tmp.txt". This is useful because, although the system keeps track of the current drive along with the current directory of that drive, it also keeps track of the current directories of all of the different drive letters if your system has more than one.
As stated previously, you cannot use the "\\?\" prefix with a relative path because it is considered a form of UNC naming.
Short and Long File Names and Paths
Typically, Windows stores the long file names on disk as special directory entries, which can be disabled systemwide for
performance reasons depending on the particular file system. When you create a long file name, Windows may also create a short MS-DOS (8.3) form of the
name, called the 8.3 alias, and store it on disk. Starting with Windows 7 and Windows Server 2008 R2, this can also be disabled for a specified volume. On many file systems, a short file name contains a tilde (~) character within each component when it is too long to comply with 8.3 naming rules, as previously discussed.
Note Not all file systems
follow this convention, and systems can be configured to disable 8.3 alias generation even if they normally support it. Therefore, do not make the assumption that the 8.3 alias already exists.
To request 8.3 file names, long file names, or the full path of a file from the system, consider the following options:
On newer file systems, such as NTFS, exFAT, UDFS, and FAT32, Windows stores the long file names on disk in Unicode, which means that the original long file name is always
preserved. This is true even if a long file name contains extended characters and regardless of the code page that is active during a disk
read or write operation. The case of the file name is preserved, even when the file system is not case-sensitive.
Files using long file names can be copied between NTFS
file system partitions and Windows FAT file system partitions without losing any file name information. This may not be true for MS-DOS FAT and some types of CDFS (CD-ROM) file systems, depending on the actual file name. In this case, the short file name is substituted if possible.
Send comments about this topic to Microsoft
Build date: 6/25/2009