% File src/library/utils/man/changedFiles.Rd
% Part of the R package, https://www.R-project.org
% Copyright 2013 R Core Team
% Distributed under GPL 2 or later

\name{changedFiles}
\alias{fileSnapshot}
\alias{changedFiles}
\alias{print.changedFiles}
\alias{print.fileSnapshot}
\title{Detect which Files Have Changed}
\description{
\code{fileSnapshot} takes a snapshot of a selection of files,
recording summary information about each.  \code{changedFiles}
compares two snapshots, or compares one snapshot to the current state
of the file system.  The snapshots need not be the same directory;
this could be used to compare two directories.
}
\usage{
fileSnapshot(path = ".", file.info = TRUE, timestamp = NULL, 
	    md5sum = FALSE, digest = NULL, full.names = length(path) > 1,
	    ...) 

changedFiles(before, after, path = before$path, timestamp = before$timestamp, 
	    check.file.info = c("size", "isdir", "mode", "mtime"), 
	    md5sum = before$md5sum, digest = before$digest, 
	    full.names = before$full.names, ...)
	    
\S3method{print}{fileSnapshot}(x, verbose = FALSE, ...)

\S3method{print}{changedFiles}(x, verbose = FALSE, ...) 
} 

\arguments{ 

\item{path}{character vector; the path(s) to record. }
\item{file.info}{logical; whether to record \code{\link{file.info}}
values for each file.
}  

\item{timestamp}{character string or \code{NULL}; the name of a file
to write at the time the snapshot is taken.  This gives a quick test
for modification, but may be unreliable; see the Details. }

\item{md5sum}{logical; whether MD5 summaries of each file should be
taken as part of the snapshot. }

\item{digest}{a function or \code{NULL}; a function with header
\code{function(filename)} which will take a vector of filenames and
produce a vector of values of the same length, or a matrix with that
number of rows. }

\item{full.names}{logical; whether full names (as in
\code{\link{list.files}}) should be recorded. Must be \code{TRUE} if
\code{length(path) > 1}. }

\item{\dots}{ additional parameters to pass to
\code{\link{list.files}} to control the set of files in the snapshots.
}

\item{before, after}{objects produced by \code{fileSnapshot}; two
snapshots to compare.  If \code{after} is missing, a new snapshot of
the current file system will be produced for comparison, using
arguments recorded in \code{before} as defaults. }

\item{check.file.info}{character vector; which columns from
\code{\link{file.info}} should be compared. }

\item{x}{the object to print. }

\item{verbose}{logical; whether to list all data when printing. }

}
\details{

The \code{fileSnapshot} function uses \code{\link{list.files}} to
obtain a list of files, and depending on the \code{file.info},
\code{md5sum}, and \code{digest} arguments, records information about
each file.

The \code{changedFiles} function compares two snapshots. 

If the \code{timestamp} argument to \code{fileSnapshot} is length 1, a
file with that name is created. If it is length 1 in
\code{changedFiles}, the \code{\link{file_test}} function is used to
compare the age of all files common to both \code{before} and
\code{after} to it.  This test may be unreliable:  it compares the
current modification time of the \code{after} files to the timestamp;
that may not be the same as the modification time when the
\code{after} snapshot was taken.  It may also give incorrect results
if the clock on the file system holding the timestamp differs from the
one holding the snapshot files.

If the \code{check.file.info} argument contains a non-empty character
vector, the indicated columns from the result of a call to
\code{\link{file.info}} will be compared.

If \code{md5sum} is \code{TRUE}, \code{fileSnapshot} will call the
\code{tools::\link{md5sum}} function to record the 32 byte MD5
checksum for each file, and \code{changedFiles} will compare the
values.  The \code{digest} argument allows users to provide their own
digest function.

}

\value{

\code{fileSnapshot} returns an object of class \code{"fileSnapshot"}.
This is a list containing the fields 

\item{info}{a data frame whose rownames are the filenames, and whose
columns contain the requested snapshot data} 

\item{path}{the normalized \code{path} from the call} 

\item{timestamp, file.info, md5sum, digest, full.names}{a record of
the other arguments from the call} 

\item{args}{other arguments passed via \code{...} to
\code{\link{list.files}}.}

\code{changedFiles} produces an object of class \code{"changedFiles"}.
This is a list containing

\item{added, deleted, changed, unchanged}{character vectors of
filenames from the before and after snapshots, with obvious meanings}

\item{changes}{a logical matrix with a row for each common file, and a
column for each comparison test. \code{TRUE} indicates a change in
that test.}

\code{\link{print}} methods are defined for each of these types.  The
\code{\link{print}} method for \code{"fileSnapshot"} objects
displays the arguments used to produce them, while the one for
\code{"changedFiles"} displays the \code{added}, \code{deleted} and
\code{changed} fields if non-empty, and a submatrix of the
\code{changes} matrix containing all of the \code{TRUE} values.

}

\author{
Duncan Murdoch, using suggestions from Karl Millar and others.
}

\seealso{
\code{\link{file.info}}, \code{\link{file_test}}, \code{\link{md5sum}}.
}

\examples{
# Create some files in a temporary directory
dir <- tempfile()
dir.create(dir)
writeBin(1L, file.path(dir, "file1"))
writeBin(2L, file.path(dir, "file2"))
dir.create(file.path(dir, "dir"))

# Take a snapshot
snapshot <- fileSnapshot(dir, timestamp = tempfile("timestamp"), md5sum=TRUE)
\dontshow{Sys.sleep(.01)}  % avoid spurious Rdiff below
# Change one of the files.
writeBin(3L:4L, file.path(dir, "file2"))

# Display the detected changes.  We may or may not see mtime change...
changedFiles(snapshot)
changedFiles(snapshot)$changes
}
\keyword{utilities}
\keyword{file}
