.\" Automatically generated by Pod::Man 2.27 (Pod::Simple 3.28)
.\"
.\" Standard preamble:
.\" ========================================================================
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
..
.de Vb \" Begin verbatim text
.ft CW
.nf
.ne \\$1
..
.de Ve \" End verbatim text
.ft R
.fi
..
.\" Set up some character translations and predefined strings. \*(-- will
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
.\" double quote, and \*(R" will give a right double quote. \*(C+ will
.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
.\" nothing in troff, for use with C<>.
.tr \(*W-
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
.ie n \{\
. ds -- \(*W-
. ds PI pi
. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
. ds L" ""
. ds R" ""
. ds C` ""
. ds C' ""
'br\}
.el\{\
. ds -- \|\(em\|
. ds PI \(*p
. ds L" ``
. ds R" ''
. ds C`
. ds C'
'br\}
.\"
.\" Escape single quotes in literal strings from groff's Unicode transform.
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.\"
.\" If the F register is turned on, we'll generate index entries on stderr for
.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
.\" entries marked with X<> in POD. Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
.\"
.\" Avoid warning from groff about undefined register 'F'.
.de IX
..
.nr rF 0
.if \n(.g .if rF .nr rF 1
.if (\n(rF:(\n(.g==0)) \{
. if \nF \{
. de IX
. tm Index:\\$1\t\\n%\t"\\$2"
..
. if !\nF==2 \{
. nr % 0
. nr F 2
. \}
. \}
.\}
.rr rF
.\"
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
.\" Fear. Run. Save yourself. No user-serviceable parts.
. \" fudge factors for nroff and troff
.if n \{\
. ds #H 0
. ds #V .8m
. ds #F .3m
. ds #[ \f1
. ds #] \fP
.\}
.if t \{\
. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
. ds #V .6m
. ds #F 0
. ds #[ \&
. ds #] \&
.\}
. \" simple accents for nroff and troff
.if n \{\
. ds ' \&
. ds ` \&
. ds ^ \&
. ds , \&
. ds ~ ~
. ds /
.\}
.if t \{\
. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
.\}
. \" troff and (daisy-wheel) nroff accents
.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
.ds ae a\h'-(\w'a'u*4/10)'e
.ds Ae A\h'-(\w'A'u*4/10)'E
. \" corrections for vroff
.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
. \" for low resolution devices (crt and lpr)
.if \n(.H>23 .if \n(.V>19 \
\{\
. ds : e
. ds 8 ss
. ds o a
. ds d- d\h'-1'\(ga
. ds D- D\h'-1'\(hy
. ds th \o'bp'
. ds Th \o'LP'
. ds ae ae
. ds Ae AE
.\}
.rm #[ #] #H #V #F C
.\" ========================================================================
.\"
.IX Title "Test::File 3"
.TH Test::File 3 "2022-12-31" "perl v5.16.3" "User Contributed Perl Documentation"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
.nh
.SH "NAME"
Test::File \-\- test file attributes
.SH "SYNOPSIS"
.IX Header "SYNOPSIS"
.Vb 1
\& use Test::File;
.Ve
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
This modules provides a collection of test utilities for file
attributes.
.PP
Some file attributes depend on the owner of the process testing the
file in the same way the file test operators do. For instance, root
(or super-user or Administrator) may always be able to read files no
matter the permissions.
.PP
Some attributes don't make sense outside of Unix, either, so some
tests automatically skip if they think they won't work on the
platform. If you have a way to make these functions work on Windows,
for instance, please send me a patch. :) If you want to pretend to be
Windows on a non-Windows machine (for instance, to test \f(CW\*(C`skip()\*(C'\fR),
you can set the \f(CW\*(C`PRETEND_TO_BE_WINDOWS\*(C'\fR environment variable.
.PP
The optional \s-1NAME\s0 parameter for every function allows you to specify a
name for the test. If not supplied, a reasonable default will be
generated.
.SS "Functions"
.IX Subsection "Functions"
.IP "has_symlinks" 4
.IX Item "has_symlinks"
Returns true is this module thinks that the current system supports
symlinks.
.Sp
This is not a test function. It's something that tests can use to
determine what it should expect or skip.
.IP "file_exists_ok( \s-1FILENAME\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_exists_ok( FILENAME [, NAME ] )"
Ok if the file exists, and not ok otherwise.
.IP "file_not_exists_ok( \s-1FILENAME\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_not_exists_ok( FILENAME [, NAME ] )"
Ok if the file does not exist, and not okay if it does exist.
.IP "file_empty_ok( \s-1FILENAME\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_empty_ok( FILENAME [, NAME ] )"
Ok if the file exists and has empty size, not ok if the file does not
exist or exists with non-zero size.
.Sp
Previously this tried to test any sort of file. Sometime in the future
this will fail if the argument is not a plain file or is a directory.
.IP "file_not_empty_ok( \s-1FILENAME\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_not_empty_ok( FILENAME [, NAME ] )"
Ok if the file exists and has non-zero size, not ok if the file does
not exist or exists with zero size.
.Sp
Previously this tried to test any sort of file. Sometime in the future
this will fail if the argument is not a plain file or is a directory.
.IP "file_size_ok( \s-1FILENAME, SIZE\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_size_ok( FILENAME, SIZE [, NAME ] )"
Ok if the file exists and has \s-1SIZE\s0 size in bytes (exactly), not ok if
the file does not exist or exists with size other than \s-1SIZE.\s0
.Sp
Previously this tried to test any sort of file. Sometime in the future
this will fail if the argument is not a plain file or is a directory.
.IP "file_max_size_ok( \s-1FILENAME, MAX\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_max_size_ok( FILENAME, MAX [, NAME ] )"
Ok if the file exists and has size less than or equal to \s-1MAX\s0 bytes, not
ok if the file does not exist or exists with size greater than \s-1MAX\s0
bytes.
.Sp
Previously this tried to test any sort of file. Sometime in the future
this will fail if the argument is not a plain file or is a directory.
.IP "file_min_size_ok( \s-1FILENAME, MIN\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_min_size_ok( FILENAME, MIN [, NAME ] )"
Ok if the file exists and has size greater than or equal to \s-1MIN\s0 bytes,
not ok if the file does not exist or exists with size less than \s-1MIN\s0
bytes.
.Sp
Previously this tried to test any sort of file. Sometime in the future
this will fail if the argument is not a plain file or is a directory.
.IP "file_line_count_is( \s-1FILENAME, COUNT\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_line_count_is( FILENAME, COUNT [, NAME ] )"
Ok if the file exists and has \s-1COUNT\s0 lines (exactly), not ok if the
file does not exist or exists with a line count other than \s-1COUNT.\s0
.Sp
This function uses the current value of \f(CW$/\fR as the line ending and
counts the lines by reading them and counting how many it read.
.Sp
Previously this tried to test any sort of file. Sometime in the future
this will fail if the argument is not a plain file or is a directory.
.IP "file_line_count_isnt( \s-1FILENAME, COUNT\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_line_count_isnt( FILENAME, COUNT [, NAME ] )"
Ok if the file exists and doesn't have exactly \s-1COUNT\s0 lines, not ok if
the file does not exist or exists with a line count of \s-1COUNT.\s0 Read
that carefully: the file must exist for this test to pass!
.Sp
This function uses the current value of \f(CW$/\fR as the line ending and
counts the lines by reading them and counting how many it read.
.Sp
Previously this tried to test any sort of file. Sometime in the future
this will fail if the argument is not a plain file or is a directory.
.IP "file_line_count_between( \s-1FILENAME, MIN, MAX,\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_line_count_between( FILENAME, MIN, MAX, [, NAME ] )"
Ok if the file exists and has a line count between \s-1MIN\s0 and \s-1MAX,\s0
inclusively.
.Sp
This function uses the current value of \f(CW$/\fR as the line ending and
counts the lines by reading them and counting how many it read.
.Sp
Previously this tried to test any sort of file. Sometime in the future
this will fail if the argument is not a plain file or is a directory.
.IP "file_contains_like ( \s-1FILENAME, PATTERN\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_contains_like ( FILENAME, PATTERN [, NAME ] )"
Ok if the file exists and its contents (as one big string) match
\&\s-1PATTERN,\s0 not ok if the file does not exist, is not readable, or exists
but doesn't match \s-1PATTERN.\s0
.Sp
Since the file contents are read into memory, you should not use this
for large files. Besides memory consumption, test diagnostics for
failing tests might be difficult to decipher. However, for short
files this works very well.
.Sp
Because the entire contents are treated as one large string, you can
make a pattern that tests multiple lines. Don't forget that you may
need to use the /s modifier for such patterns:
.Sp
.Vb 2
\& # make sure file has one or more paragraphs with CSS class X
\& file_contains_like($html_file, qr{
.*?
}s);
.Ve
.Sp
Contrariwise, if you need to match at the beginning or end of a line
inside the file, use the /m modifier:
.Sp
.Vb 2
\& # make sure file has a setting for foo
\& file_contains_like($config_file, qr/^ foo \es* = \es* \ew+ $/mx);
.Ve
.Sp
If you want to test your file contents against multiple patterns, but
don't want to have the file read in repeatedly, you can pass an
arrayref of patterns instead of a single pattern, like so:
.Sp
.Vb 7
\& # make sure our template has rendered correctly
\& file_contains_like($template_out,
\& [
\& qr/^ $title_line $/mx,
\& map { qr/^ $_ $/mx } @chapter_headings,
\& qr/^ $footer_line $/mx,
\& ]);
.Ve
.Sp
Please note that if you do this, and your file does not exist or is
not readable, you'll only get one test failure instead of a failure
for each pattern. This could cause your test plan to be off, although
you may not care at that point because your test failed anyway. If
you do care, either skip the test plan altogether by employing
Test::More's \f(CW\*(C`done_testing()\*(C'\fR function, or use
\&\*(L"file_readable_ok\*(R" in conjunction with a \f(CW\*(C`SKIP\*(C'\fR block.
.Sp
Contributed by Buddy Burden \f(CW\*(C`\*(C'\fR.
.IP "file_contains_unlike ( \s-1FILENAME, PATTERN\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_contains_unlike ( FILENAME, PATTERN [, NAME ] )"
Ok if the file exists and its contents (as one big string) do \fBnot\fR
match \s-1PATTERN,\s0 not ok if the file does not exist, is not readable, or
exists but matches \s-1PATTERN.\s0
.Sp
All notes and caveats for \*(L"file_contains_like\*(R" apply to this
function as well.
.Sp
Contributed by Buddy Burden \f(CW\*(C`\*(C'\fR.
.IP "file_contains_utf8_like ( \s-1FILENAME, PATTERN\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_contains_utf8_like ( FILENAME, PATTERN [, NAME ] )"
The same as \f(CW\*(C`file_contains_like\*(C'\fR, except the file is opened as \s-1UTF\-8.\s0
.IP "file_contains_utf8_unlike ( \s-1FILENAME, PATTERN\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_contains_utf8_unlike ( FILENAME, PATTERN [, NAME ] )"
The same as \f(CW\*(C`file_contains_unlike\*(C'\fR, except the file is opened as \s-1UTF\-8.\s0
.IP "file_contains_encoded_like ( \s-1FILENAME, ENCODING, PATTERN\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_contains_encoded_like ( FILENAME, ENCODING, PATTERN [, NAME ] )"
The same as \f(CW\*(C`file_contains_like\*(C'\fR, except the file is opened with \s-1ENCODING\s0
.IP "file_contains_encoded_unlike ( \s-1FILENAME, ENCODING, PATTERN\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_contains_encoded_unlike ( FILENAME, ENCODING, PATTERN [, NAME ] )"
The same as \f(CW\*(C`file_contains_unlike\*(C'\fR, except the file is opened with \s-1ENCODING.\s0
.IP "file_readable_ok( \s-1FILENAME\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_readable_ok( FILENAME [, NAME ] )"
Ok if the file exists and is readable, not ok if the file does not
exist or is not readable.
.IP "file_not_readable_ok( \s-1FILENAME\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_not_readable_ok( FILENAME [, NAME ] )"
Ok if the file exists and is not readable, not ok if the file does not
exist or is readable.
.IP "file_writable_ok( \s-1FILENAME\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_writable_ok( FILENAME [, NAME ] )"
.PD 0
.IP "file_writeable_ok( \s-1FILENAME\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_writeable_ok( FILENAME [, NAME ] )"
.PD
Ok if the file exists and is writable, not ok if the file does not
exist or is not writable.
.Sp
The original name is \f(CW\*(C`file_writeable_ok\*(C'\fR with that extra \fIe\fR. That
still works but there's a function with the correct spelling too.
.IP "file_not_writeable_ok( \s-1FILENAME\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_not_writeable_ok( FILENAME [, NAME ] )"
.PD 0
.IP "file_not_writable_ok( \s-1FILENAME\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_not_writable_ok( FILENAME [, NAME ] )"
.PD
Ok if the file exists and is not writable, not ok if the file does not
exist or is writable.
.Sp
The original name is \f(CW\*(C`file_not_writeable_ok\*(C'\fR with that extra \fIe\fR.
That still works but there's a function with the correct spelling too.
.IP "file_executable_ok( \s-1FILENAME\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_executable_ok( FILENAME [, NAME ] )"
Ok if the file exists and is executable, not ok if the file does not
exist or is not executable.
.Sp
This test automatically skips if it thinks it is on a Windows
platform.
.IP "file_not_executable_ok( \s-1FILENAME\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_not_executable_ok( FILENAME [, NAME ] )"
Ok if the file exists and is not executable, not ok if the file does
not exist or is executable.
.Sp
This test automatically skips if it thinks it is on a Windows
platform.
.IP "file_mode_is( \s-1FILENAME, MODE\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_mode_is( FILENAME, MODE [, NAME ] )"
Ok if the file exists and the mode matches, not ok if the file does
not exist or the mode does not match.
.Sp
This test automatically skips if it thinks it is on a Windows
platform.
.Sp
Contributed by Shawn Sorichetti \f(CW\*(C`\*(C'\fR
.IP "file_mode_isnt( \s-1FILENAME, MODE\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_mode_isnt( FILENAME, MODE [, NAME ] )"
Ok if the file exists and mode does not match, not ok if the file does
not exist or mode does match.
.Sp
This test automatically skips if it thinks it is on a Windows
platform.
.Sp
Contributed by Shawn Sorichetti \f(CW\*(C`\*(C'\fR
.IP "file_mode_has( \s-1FILENAME, MODE\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_mode_has( FILENAME, MODE [, NAME ] )"
Ok if the file exists and has all the bits in mode turned on, not ok
if the file does not exist or the mode does not match. That is, \f(CW\*(C`FILEMODE & MODE == MODE\*(C'\fR must be true.
.Sp
This test automatically skips if it thinks it is on a Windows
platform.
.Sp
Contributed by Ricardo Signes \f(CW\*(C`\*(C'\fR
.IP "file_mode_hasnt( \s-1FILENAME, MODE\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_mode_hasnt( FILENAME, MODE [, NAME ] )"
Ok if the file exists and has all the bits in mode turned off, not ok
if the file does not exist or the mode does not match. That is,
\&\f(CW\*(C`FILEMODE & MODE == 0\*(C'\fR must be true.
.Sp
This test automatically skips if it thinks it is on a
Windows platform.
.Sp
Contributed by Ricardo Signes \f(CW\*(C`\*(C'\fR
.IP "file_is_symlink_ok( \s-1FILENAME\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_is_symlink_ok( FILENAME [, NAME ] )"
Ok if \s-1FILENAME\s0 is a symlink, even if it points to a non-existent
file. This test automatically skips if the operating system does
not support symlinks.
.IP "file_is_not_symlink_ok( \s-1FILENAME\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_is_not_symlink_ok( FILENAME [, NAME ] )"
Ok if \s-1FILENAME\s0 is a not symlink. This test automatically skips if the
operating system does not support symlinks. If the file does not
exist, the test fails.
.IP "symlink_target_exists_ok( \s-1SYMLINK\s0 [, \s-1TARGET\s0] [, \s-1NAME \s0] )" 4
.IX Item "symlink_target_exists_ok( SYMLINK [, TARGET] [, NAME ] )"
Ok if \s-1FILENAME\s0 is a symlink and it points to a existing file. With the
optional \s-1TARGET\s0 argument, the test fails if \s-1SYMLINK\s0's target is not
\&\s-1TARGET.\s0 This test automatically skips if the operating system does not
support symlinks. If the file does not exist, the test fails.
.IP "symlink_target_dangles_ok( \s-1SYMLINK\s0 [, \s-1NAME \s0] )" 4
.IX Item "symlink_target_dangles_ok( SYMLINK [, NAME ] )"
Ok if \s-1FILENAME\s0 is a symlink and if it doesn't point to a existing
file. This test automatically skips if the operating system does not
support symlinks. If the file does not exist, the test fails.
.IP "symlink_target_is( \s-1SYMLINK, TARGET\s0 [, \s-1NAME \s0] )" 4
.IX Item "symlink_target_is( SYMLINK, TARGET [, NAME ] )"
Ok if \s-1FILENAME\s0 is a symlink and if points to \s-1TARGET.\s0 This test
automatically skips if the operating system does not support symlinks.
If the file does not exist, the test fails.
.IP "symlink_target_is_absolute_ok( \s-1SYMLINK\s0 [, \s-1NAME \s0] )" 4
.IX Item "symlink_target_is_absolute_ok( SYMLINK [, NAME ] )"
Ok if \s-1FILENAME\s0 is a symlink and if its target is an absolute path.
This test automatically skips if the operating system does not support
symlinks. If the file does not exist, the test fails.
.IP "dir_exists_ok( \s-1DIRECTORYNAME\s0 [, \s-1NAME \s0] )" 4
.IX Item "dir_exists_ok( DIRECTORYNAME [, NAME ] )"
Ok if the file exists and is a directory, not ok if the file doesn't exist, or exists but isn't a
directory.
.Sp
Contributed by Buddy Burden \f(CW\*(C`\*(C'\fR.
.IP "dir_contains_ok( \s-1DIRECTORYNAME, FILENAME\s0 [, \s-1NAME \s0] )" 4
.IX Item "dir_contains_ok( DIRECTORYNAME, FILENAME [, NAME ] )"
Ok if the directory exists and contains the file, not ok if the directory doesn't exist, or exists
but doesn't contain the file.
.Sp
Contributed by Buddy Burden \f(CW\*(C`\*(C'\fR.
.IP "link_count_is_ok( \s-1FILE, LINK_COUNT\s0 [, \s-1NAME \s0] )" 4
.IX Item "link_count_is_ok( FILE, LINK_COUNT [, NAME ] )"
Ok if the link count to \s-1FILE\s0 is \s-1LINK_COUNT. LINK_COUNT\s0 is interpreted
as an integer. A \s-1LINK_COUNT\s0 that evaluates to 0 returns Ok if the file
does not exist.
.IP "link_count_gt_ok( \s-1FILE, LINK_COUNT\s0 [, \s-1NAME \s0] )" 4
.IX Item "link_count_gt_ok( FILE, LINK_COUNT [, NAME ] )"
Ok if the link count to \s-1FILE\s0 is greater than \s-1LINK_COUNT. LINK_COUNT\s0 is
interpreted as an integer. A \s-1LINK_COUNT\s0 that evaluates to 0 returns Ok
if the file has at least one link.
.IP "link_count_lt_ok( \s-1FILE, LINK_COUNT\s0 [, \s-1NAME \s0] )" 4
.IX Item "link_count_lt_ok( FILE, LINK_COUNT [, NAME ] )"
Ok if the link count to \s-1FILE\s0 is less than \s-1LINK_COUNT. LINK_COUNT\s0 is
interpreted as an integer. A \s-1LINK_COUNT\s0 that evaluates to 0 returns Ok
if the file has at least one link.
.IP "owner_is( \s-1FILE , OWNER\s0 [, \s-1NAME \s0] )" 4
.IX Item "owner_is( FILE , OWNER [, NAME ] )"
Ok if \s-1FILE\s0's owner is the same as \s-1OWNER. OWNER\s0 may be a text user name
or a numeric userid. Test skips on Dos, and Mac \s-1OS\s0 <= 9.
If the file does not exist, the test fails.
.Sp
Contributed by Dylan Martin
.IP "owner_isnt( \s-1FILE, OWNER\s0 [, \s-1NAME \s0] )" 4
.IX Item "owner_isnt( FILE, OWNER [, NAME ] )"
Ok if \s-1FILE\s0's owner is not the same as \s-1OWNER. OWNER\s0 may be a text user name
or a numeric userid. Test skips on Dos and Mac \s-1OS\s0 <= 9. If the file
does not exist, the test fails.
.Sp
Contributed by Dylan Martin
.IP "group_is( \s-1FILE , GROUP\s0 [, \s-1NAME \s0] )" 4
.IX Item "group_is( FILE , GROUP [, NAME ] )"
Ok if \s-1FILE\s0's group is the same as \s-1GROUP. GROUP\s0 may be a text group name or
a numeric group id. Test skips on Dos, Mac \s-1OS\s0 <= 9 and any other operating
systems that do not support \fIgetpwuid()\fR and friends. If the file does not
exist, the test fails.
.Sp
Contributed by Dylan Martin
.IP "group_isnt( \s-1FILE , GROUP\s0 [, \s-1NAME \s0] )" 4
.IX Item "group_isnt( FILE , GROUP [, NAME ] )"
Ok if \s-1FILE\s0's group is not the same as \s-1GROUP. GROUP\s0 may be a text group name or
a numeric group id. Test skips on Dos, Mac \s-1OS\s0 <= 9 and any other operating
systems that do not support \fIgetpwuid()\fR and friends. If the file does not
exist, the test fails.
.Sp
Contributed by Dylan Martin
.IP "file_mtime_age_ok( \s-1FILE\s0 [, \s-1WITHIN_SECONDS \s0] [, \s-1NAME \s0] )" 4
.IX Item "file_mtime_age_ok( FILE [, WITHIN_SECONDS ] [, NAME ] )"
Ok if \s-1FILE\s0's modified time is \s-1WITHIN_SECONDS\s0 inclusive of the system's current time.
This test uses \fIstat()\fR to obtain the mtime. If the file does not exist the test
returns failure. If \fIstat()\fR fails, the test is skipped.
.IP "file_mtime_gt_ok( \s-1FILE, UNIXTIME\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_mtime_gt_ok( FILE, UNIXTIME [, NAME ] )"
Ok if \s-1FILE\s0's mtime is > \s-1UNIXTIME.\s0 This test uses \fIstat()\fR to get the mtime. If \fIstat()\fR fails
this test is skipped. If \s-1FILE\s0 does not exist, this test fails.
.IP "file_mtime_lt_ok( \s-1FILE, UNIXTIME,\s0 [, \s-1NAME \s0] )" 4
.IX Item "file_mtime_lt_ok( FILE, UNIXTIME, [, NAME ] )"
Ok if \s-1FILE\s0's modified time is < \s-1UNIXTIME. \s0 This test uses \fIstat()\fR to get the mtime. If \fIstat()\fR fails
this test is skipped. If \s-1FILE\s0 does not exist, this test fails.
.SH "TO DO"
.IX Header "TO DO"
* check properties for other users (readable_by_root, for instance)
.PP
* check times
.PP
* check number of links to file
.PP
* check path parts (directory, filename, extension)
.SH "SEE ALSO"
.IX Header "SEE ALSO"
Test::Builder,
Test::More
.PP
If you are using the new \f(CW\*(C`Test2\*(C'\fR stuff, see Test2::Tools::File
(https://github.com/torbjorn/Test2\-Tools\-File).
.SH "SOURCE AVAILABILITY"
.IX Header "SOURCE AVAILABILITY"
This module is in Github:
.PP
.Vb 1
\& https://github.com/briandfoy/test\-file
.Ve
.SH "AUTHOR"
.IX Header "AUTHOR"
brian d foy, \f(CW\*(C`\*(C'\fR
.SH "CREDITS"
.IX Header "CREDITS"
Shawn Sorichetti \f(CW\*(C`\*(C'\fR provided
some functions.
.PP
Tom Metro helped me figure out some Windows capabilities.
.PP
Dylan Martin added \f(CW\*(C`owner_is\*(C'\fR and \f(CW\*(C`owner_isnt\*(C'\fR.
.PP
David Wheeler added \f(CW\*(C`file_line_count_is\*(C'\fR.
.PP
Buddy Burden \f(CW\*(C`\*(C'\fR provided \f(CW\*(C`dir_exists_ok\*(C'\fR,
\&\f(CW\*(C`dir_contains_ok\*(C'\fR, \f(CW\*(C`file_contains_like\*(C'\fR, and
\&\f(CW\*(C`file_contains_unlike\*(C'\fR.
.PP
xmikew \f(CW\*(C`\*(C'\fR provided the \f(CW\*(C`mtime_age\*(C'\fR
stuff.
.PP
Torbjo\*/rn Lindahl is working on Test2::Tools::File and we're
working together to align our interfaces.
.PP
Jean-Damien Durand added bits to use Win32::IsSymlinkCreationAllowed,
new since Win32 0.55.
.SH "COPYRIGHT AND LICENSE"
.IX Header "COPYRIGHT AND LICENSE"
Copyright X 2002\-2023, brian d foy . All rights reserved.
.PP
This program is free software; you can redistribute it and/or modify
it under the terms of the Artistic License 2.0