View Source Xfile (xfile v0.4.0)
Xfile
contains augmentations of the built-in File
module, including the
support of streams, the recursive listing of files, counting lines, grep, and
programmatic filtering.
Link to this section Summary
Functions
Like the venerable command-line utility, grep
searches lines in the given file
using the given pattern, returning only the matching lines as a stream.
This function mimics the functionality of grep -rl
: it recursively searches
all files in the given path, returning only a list of file names (i.e. paths)
whose contents have one or more lines that match the pattern.
Displays first n
lines of the file, returned as an enumerable stream.
As Xfile.line_count/1
, but returns raw results on success or raises on :error
.
Counts the number of lines in the given file, offering functionality similar to wc -l
.
Directories are not allowed. This is just some sugar around File.stream!/1
.
As Xfile.ls/2
, but returns raw results on success or raises on :error
.
Returns the list of files in the given directory with the ability to control listing files recursively and filtering results programmatically.
Displays the last n
lines of the file, returned as an enumerable stream.
Link to this section Functions
@spec grep(pattern :: String.pattern() | (String.t() -> boolean()), file :: Path.t()) :: Enumerable.t()
Like the venerable command-line utility, grep
searches lines in the given file
using the given pattern, returning only the matching lines as a stream.
The given pattern can be one of the following:
- an arity 1 function which returns a boolean;
true
indicates a match. - a string
- a list of strings
- a regular expression
See String.contains?/2
for viable inputs.
Stream
Xfile.grep/2
returns its result as aStream
, so you must remember to convert it to a list viaEnum.to_list/1
if you are not lazily evaluating its result.
examples
Examples
iex> Xfile.grep(~r/needle/, "path/to/file")
#Function<59.58486609/2 in Stream.transform/3>
iex> Xfile.grep("dir", ".gitignore") |> Enum.to_list()
["# The directory Mix will write compiled artifacts to.\n",
"# The directory Mix downloads your dependencies sources to.\n"]
Using a function to evaluate file lines:
iex> f = fn line ->
[serial_number, _] = String.split(line, " ")
String.to_integer(num) > 214
end
iex> Xfile.grep(f, "store/products.csv") |> Enum.to_list()
["215,Sprocket,9.99\n", "216,Gear,5.00\n", ...]
@spec grep_rl(pattern :: String.pattern(), path :: Path.t(), opts :: Keyword.t()) :: Enumerable.t()
This function mimics the functionality of grep -rl
: it recursively searches
all files in the given path, returning only a list of file names (i.e. paths)
whose contents have one or more lines that match the pattern.
pattern
Pattern
The given pattern can be one of the following:
- an arity 1 function which returns a boolean;
true
indicates a match. - a string
- a list of strings
- a regular expression
Internally, this relies on grep/2
.
Stream
Xfile.grep_rl/3
returns its result as aStream
, so you must remember to convert it to a list viaEnum.to_list/1
if you are not lazily evaluating its result.
options
Options
Options are the same as those supported by ls/2
. Use them to control which files
are subjected to the pattern matching.
examples
Examples
iex> Xfile.grep_rl("[error]", "tmp/logs", recursive: false) |> Enum.to_list()
[
"tmp/logs/server.1.log",
"tmp/logs/cache.log",
"tmp/logs/server.2.log"
]
see-also
See Also
@spec head(file :: Path.t(), n :: non_neg_integer()) :: Enumerable.t()
Displays first n
lines of the file, returned as an enumerable stream.
examples
Examples
iex> Xfile.head(".gitignore", 3) |> Enum.to_list()
[
"# The directory Mix will write compiled artifacts to.\n",
"/_build/\n",
"\n"
]
@spec line_count!(file :: Path.t()) :: non_neg_integer() | none()
As Xfile.line_count/1
, but returns raw results on success or raises on :error
.
examples
Examples
iex> Xfile.line_count!(".gitignore")
27
@spec line_count(file :: Path.t()) :: {:ok, non_neg_integer()}
Counts the number of lines in the given file, offering functionality similar to wc -l
.
Directories are not allowed. This is just some sugar around File.stream!/1
.
Newlines
This function technically counts new lines, which may result in "off-by-one" errors when the last line of a file is not terminated with a newline.
examples
Examples
iex> Xfile.line_count(".gitignore")
{:ok, 27}
iex> Xfile.line_count("/tmp"}
{:error, "Invalid input"}
@spec ls!(directory :: Path.t(), opts :: Keyword.t()) :: Enumerable.t() | none()
As Xfile.ls/2
, but returns raw results on success or raises on :error
.
@spec ls(directory :: Path.t(), opts :: Keyword.t()) :: {:ok, Enumerable.t()} | {:error, any()}
Returns the list of files in the given directory with the ability to control listing files recursively and filtering results programmatically.
Stream
Unlike
File.ls/1
,Xfile.ls/2
returns its result as aStream
, so you must remember to convert it to a list viaEnum.to_list/1
if you are not lazily evaluating its result.
differences-between-file-ls-1
Differences between File.ls/1
Xfile.ls/2
returns results as aStream
Xfile.ls/2
returns full paths (relative or absolute) instead of just basenames.
options
Options
:recursive
indicates whether the directory and its subdirectories should be recursively searched. This can be expressed either as a simple boolean or as a positive integer indicating the maximum depth (wherefalse
is equivalent to0
and would list only the contents of the given directory). Default:true
:filter
can be either a regular expression to be used withString.match?/2
, a string or a list of strings to be used withString.contains?/2
, OR an arity 1 function that receives the full file path and returns a boolean value. If the filter operation returnstrue
, the file will be included in the output. Any other output will cause the file to be filtered from the output. Optional.:show_dirs?
boolean. When listing the contents of a directory that contains sub-directories and:recursive
option is nottrue
, this boolean controls whether or not the sub-directories should be included in the output (provided they pass any defined:filter
). This option is ignored when:recursive
istrue
. Setting this option totrue
will yield results closer to whatFile.ls/1
returns. Default:false
.
examples
Examples
Use a regular expression to return only .txt
files:
iex> {:ok, stream} = Xfile.ls("path/to/files", filter: ~r/\.txt$/)
{:ok, #Function<59.58486609/2 in Stream.transform/3>}
iex> Enum.to_list(stream)
[
"path/to/files/a.txt",
"path/to/files/b.txt",
"path/to/files/subdir/c.txt"
]
Use a function to apply more complex logic to filter the results:
iex> {:ok, stream} = Xfile.ls("mydir", filter: fn x ->
stat = File.stat!(x)
stat.size > 1024
end)
{:ok, #Function<59.58486609/2 in Stream.transform/3>}
iex> Enum.to_list(stream)
[
"mydir/big-file",
"mydir/big-file2",
# ...
]
Limit the depth of the recursion to the given directory and its subdirectories, but no further:
iex> {:ok, stream} = Xfile.ls("top/dir", recursive: 1)
{:ok, #Function<59.58486609/2 in Stream.transform/3>}
iex> Enum.to_list(stream)
[
"top/dir/a",
"top/dir/b",
# ...
"top/dir/sub1/x",
"top/dir/sub1/y"
]
@spec tail(file :: Path.t(), n :: non_neg_integer()) :: Enumerable.t()
Displays the last n
lines of the file, returned as an enumerable stream.
examples
Examples
iex> Xfile.tail(".gitignore", 3) |> Enum.to_list()
[
"\n",
"# Temporary files for e.g. tests\n",
"/tmp\n"
]