Check that x is a valid path, possibly containing a valid filename.
Details
is_path() is intended to be used to check for valid paths before creating a
directory or a file. Therefore it imposes the following restrictions:
xshould be a non-empty character stringxshould end in a slash if it is only a volume name:C:\, notC:xshould not be a relative path of the formD:pathord:path: such paths are not guaranteed to work with functions likefile.create(). UseD:./pathord:./pathinsteadxshould not contain the characters",*,?,|,<,>, nor any of the control characters ([:cntrl:], with ASCII octal codes000through037and177, seehelp("regex")xshould not contain colons (:) after the first path component (Windows only allows colons to indicate volume names likeC:\)path components (i.e., parts separated by file separators
/or\\) should not be the Windows-reserved termsCON,PRN,AUX,NUL,COM<non-zero digit>,LPT<non-zero digit>, case-insensitive variants of these names, or these names followed by an extensionpath components should not end with a space
path components should not end with a dot, with the exception of
"."and".."that are allowed as first component to indicate the working directory and the parent directory, respectivelyIf
xcontains a file extension (or compression extension, the current implementation does not distinguish those from each other), the part after the last slash is considered the filename, which should adhere to the restrictions listed above (although it may contain the Windows-reserved terms listed above), and in addition should not contain a colon (:), nor start with a space or a hyphen (-), nor end with a slash or backslash
These restrictions on x consider characters and path components that are
not allowed in Windows and thus would lead to an error when used to
create a directory or file; characters that are silently removed in Windows
and thus would lead to a mismatch between the created directory and the
returned path when used to create a directory; and characters that might give
problems when used in the shell.
is_path() is lenient with respect to file separators, i.e., / or \\:
xdoes not have to contain any file separator ifrequire_sepisFALSE, such thatis_path(x, require_sep = FALSE)can be used to check that filenamexonly contains allowed characters given thatxends in a file extensionxmight contain trailing file separators if it does not end in a file extension, although these trailing file separators might be ignored or removed in some operations, e.g., they are removed byfile.path()andfs::path()xmight contain successive file separators e.g.,//or\\\\: these should be treated by the operating system as if they were only a single file separator
is_path() does not check that the path in x points to an existing
file or folder, nor that such a file or folder can be created.
Notes on Paths
Slashes
The file separator is a backslash (\) on Windows but a forward slash (/)
on other operating systems: use file.path() or fs::path() to construct
paths in a platform-independent way and .Platform$file.sep to
get the file separator used on the current platform.
Furthermore, the backslash is also used as an escape character in
R, such that backslashes need to be escaped in R code by doubling them. Use
cat(x) to omit the escape characters to see how x would be printed.
Dots
The working directory can be indicated by a single dot (".") and
the parent directory can be indicated by two dots ("..").
checkinput::is_path() only allows those in the first path component.
relative paths start from the working directory. In contrast, absolute paths start from the root directory and thus give the complete path, such that the path still points to the same directory if the working directory changes.
Normalisation
Paths can be normalised, e.g., through normalizePath() or fs::path_norm()
(which is also called by fs::path_abs()). On case-insensitive file systems,
this also adjusts the case to match names of directories that are already
present.
Programming Notes
The output of tempdir() during
R CMD checks on MacOS contains
successive forward slashes (e.g.,
/var/<...>/T//RtmpxC2Fyl/working_dir/RtmpdnqgUR) which in earlier versions
of is_path() (then in package
progutils) led to
spurious warnings about duplicated file separators.
References
'Naming files, paths, and namespaces' from Microsoft
Entries Filename, Portable filenames and Pathname from the Posix standard POSIX.1-2024
'Comparison of file systems' from Wikipedia
See also
fs::path() to construct file paths in a platform-independent way;
fs::path_abs() to make paths absolute and normalised;
fs::path_math() for even more operations on paths;
fs::path_sanitize() to remove invalid characters from potential paths
progutils::create_file_path()
to create a file path, creating the directory if it does not yet exist;
progutils::create_dir()
to create a directory if it does not yet exist
progutils::get_file_path()
to check if a file exists and is a unique match to a pattern, and
fs::file_exists() and list.files() (which includes directories in its
output) to do so without checking they are a unique match to a pattern;
file.info(), file.access(), utils::file_test() and their documentation
on checking existence, permissions, and other information about files or
directories
Section
Paths in the shell
in the vignette Git and GitHub of package
checkrpkgs on paths and file separators in the
shell:
vignette("git_github", package = "checkrpkgs").
Other collections of checks on type and length:
all_characters(),
all_names(),
is_logical(),
is_natural(),
is_number(),
is_zerolength()
Examples
is_path(getwd()) # TRUE
#> [1] TRUE
is_path(fs::path_wd("abcd")) # TRUE
#> [1] TRUE
is_path(fs::path_wd("ab|cd")) # FALSE, warning about '|'
#> Warning: 'fs::path_wd("ab|cd")' should not contain '"', '*', '?', '|', '<' or '>':
#> '/home/runner/work/checkinput/checkinput/docs/reference/ab|cd'
#> [1] FALSE
is_path(fs::path_wd("abcd.txt")) # TRUE
#> [1] TRUE
is_path(fs::path_wd("abcd.txt.gz")) # TRUE
#> [1] TRUE
is_path(fs::path_wd("abcd.gz")) # TRUE
#> [1] TRUE
# ':' is only allowed in the first path component
is_path("D:/") # TRUE
#> [1] TRUE
is_path(fs::path_wd("ab:cd")) # FALSE, warning about ':'
#> Warning: Components 9 of 'fs::path_wd("ab:cd")' should not contain ':':
#> '/home/runner/work/checkinput/checkinput/docs/reference/ab:cd'
#> [1] FALSE
is_path(fs::path_wd("ab:cd.txt")) # FALSE, warning about ':'
#> Warning: Components 9 of 'fs::path_wd("ab:cd.txt")' should not contain ':':
#> '/home/runner/work/checkinput/checkinput/docs/reference/ab:cd.txt'
#> Warning: The filename ('ab:cd.txt') in 'fs::path_wd("ab:cd.txt")' should not contain ':':
#> '/home/runner/work/checkinput/checkinput/docs/reference/ab:cd.txt'
#> [1] FALSE
# Other illegal characters are not allowed
# in either paths or filenames
is_path(fs::path_wd("ab|cd")) # FALSE, warning about '|'
#> Warning: 'fs::path_wd("ab|cd")' should not contain '"', '*', '?', '|', '<' or '>':
#> '/home/runner/work/checkinput/checkinput/docs/reference/ab|cd'
#> [1] FALSE
is_path(fs::path_wd("ab|cd.txt")) # FALSE, warning about '|'
#> Warning: 'fs::path_wd("ab|cd.txt")' should not contain '"', '*', '?', '|', '<' or '>':
#> '/home/runner/work/checkinput/checkinput/docs/reference/ab|cd.txt'
#> [1] FALSE