EinsTools.Utilities.FileSystem 1.0.1-rc.1

This is a prerelease version of EinsTools.Utilities.FileSystem.
dotnet add package EinsTools.Utilities.FileSystem --version 1.0.1-rc.1
NuGet\Install-Package EinsTools.Utilities.FileSystem -Version 1.0.1-rc.1
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="EinsTools.Utilities.FileSystem" Version="1.0.1-rc.1" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add EinsTools.Utilities.FileSystem --version 1.0.1-rc.1
#r "nuget: EinsTools.Utilities.FileSystem, 1.0.1-rc.1"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install EinsTools.Utilities.FileSystem as a Cake Addin
#addin nuget:?package=EinsTools.Utilities.FileSystem&version=1.0.1-rc.1&prerelease

// Install EinsTools.Utilities.FileSystem as a Cake Tool
#tool nuget:?package=EinsTools.Utilities.FileSystem&version=1.0.1-rc.1&prerelease

EinsTools.Utilities.FileSystem

A small library with extensions to the DirectoryInfo and FileInfo classes.

DirectoryInfo Extensions

GetDirectory

public static DirectoryInfo GetDirectory(this DirectoryInfo directory, string path)

Returns a DirectoryInfo object for the specified path relative to the current directory. The path can be absolute or relative. If the path is relative, it is combined with the current directory to form an absolute path.

The function does not check if the directory exists.

var directory = new DirectoryInfo(@"C:\Temp");
var subDirectory = directory.GetDirectory("SubDirectory");

GetRequiredDirectory

public static DirectoryInfo GetRequiredDirectory(this DirectoryInfo directory, string path)

Like GetDirectory, but throws an exception if the directory does not exist.

var directory = new DirectoryInfo(@"C:\Temp");
var subDirectory = directory.GetRequiredDirectory("SubDirectory");

GetFile

public static FileInfo GetFile(this DirectoryInfo directory, string path)

Returns a FileInfo object for the specified path relative to the current directory. The path can be absolute or relative. If the path is relative, it is combined with the current directory to form an absolute path.

The function does not check if the file exists.

var directory = new DirectoryInfo(@"C:\Temp");
var file = directory.GetFile(@"SubDirectory\file.txt");

GetRequiredFile

public static FileInfo GetRequiredFile(this DirectoryInfo directory, string path)

Like GetFile, but throws an exception if the file does not exist.

var directory = new DirectoryInfo(@"C:\Temp");
var file = directory.GetRequiredFile(@"SubDirectory\file.txt");

FullNameWithEnding

public static string FullNameWithEnding(this DirectoryInfo directory)

Returns the full name of the directory with a trailing backslash or slash depending on the operating system.

Under Linux or MacOS, the function returns the full name with a trailing slash (e.g. "/home/user/"). On Windows, the function returns the full name with a trailing backslash (e.g. "C:\Users\user"). Additionally, the function will replace a trailing slash with a backslash on Windows (e.g. "C:\Users\user/" ⇒ "C:\Users\user").

var directory = new DirectoryInfo(@"C:\Temp");
var fullName = directory.FullNameWithEnding(); // "C:\Temp\" on Windows

FullNameWithoutEnding

public static string FullNameWithoutEnding(this DirectoryInfo directory)

Returns the full name of the directory without a trailing backslash or slash depending on the operating system.

var directory = new DirectoryInfo(@"C:\Temp\");
var fullName = directory.FullNameWithoutEnding(); // "C:\Temp" on Windows

EnsureDeleted

public static void EnsureDeleted(this DirectoryInfo @this, string? path = null)
public static Task EnsureDeletedAsync(this DirectoryInfo @this, string? path = null)

Deletes the directory if it exists. If path is not null, the function deletes the directory or file specified by path relative to the current directory.

If the deletion fails, the function will not throw an exception, provided the directory does not exist after the function call.

This is useful if you want to delete a directory and don't care if it existed or not and in situations where more than one process might be deleting the directory at the same time.

The async version runs asynchronously.

var directory = new DirectoryInfo(@"C:\Temp");
directory.EnsureDeleted();

GetSize

public static long GetSize(this DirectoryInfo d)
public static async Task<long> GetSizeAsync(this DirectoryInfo d)

Returns the size of the directory in bytes. The async version runs asynchronously.

var directory = new DirectoryInfo(@"C:\Temp");
var size = directory.GetSize();

CreateZipFile

public static FileInfo CreateZipFile(
    this DirectoryInfo d,
    FileInfo destination,
    CompressionLevel compressionLevel = CompressionLevel.Optimal,
    bool includeBaseDirectory = false,
    Encoding? entryNameEncoding = null)

public static FileInfo CreateZipFile(
        this DirectoryInfo directory,
        string destination,
        CompressionLevel compressionLevel = CompressionLevel.Optimal,
        bool includeBaseDirectory = false,
        Encoding? entryNameEncoding = null)

public static async Task<FileInfo> CreateZipFileAsync(
    this DirectoryInfo d,
    FileInfo destination,
    CompressionLevel compressionLevel = CompressionLevel.Optimal,
    bool includeBaseDirectory = false,
    Encoding? entryNameEncoding = null)
    
public static async Task<FileInfo> CreateZipFileAsync(
        this DirectoryInfo directory,
        string destination,
        CompressionLevel compressionLevel = CompressionLevel.Optimal,
        bool includeBaseDirectory = false,
        Encoding? entryNameEncoding = null)

Creates a zip file from the directory. The zip file is written to the specified destination file. If the destination file already exists, it is overwritten. The function returns the destination file.

If includeBaseDirectory is true, the base directory is included in the zip file. Otherwise, only the contents of the directory are included.

The entryNameEncoding parameter specifies the encoding used for the names of the entries in the zip file. If the parameter is null, the default encoding is used.

The async version runs asynchronously.

var directory = new DirectoryInfo(@"C:\Temp");
var destination = new FileInfo(@"C:\Temp\archive.zip");
var archive = directory.CreateZipFile(destination, CompressionLevel.Optimal, true);

DeleteFiles

public static void DeleteFiles(this DirectoryInfo @this, string searchPattern = "*",
SearchOption searchOption = SearchOption.TopDirectoryOnly)

Deletes all files in the directory that match the specified search pattern. The searchOption parameter specifies whether to search only the current directory or all subdirectories as well. See the documentation of the DirectoryInfo.GetFiles method for more information (https://learn.microsoft.com/en-us/dotnet/api/system.io.directoryinfo.getfiles?view=net-7.0).

var directory = new DirectoryInfo(@"C:\Temp");
directory.DeleteFiles("*.txt", SearchOption.AllDirectories);

DeleteFilesAsync

public static async Task DeleteFilesAsync(this DirectoryInfo @this, string searchPattern = "*",
SearchOption searchOption = SearchOption.TopDirectoryOnly)

Deletes all files in the directory that match the specified search pattern. Just an asynchronous version of DeleteFiles.

var directory = new DirectoryInfo(@"C:\Temp");
await directory.DeleteFilesAsync("*.txt", SearchOption.AllDirectories);

Globbing

public static IEnumerable<string> GlobRelative(this DirectoryInfo @this, params string[] pattern);
public static IEnumerable<string> GlobAbsolute(this DirectoryInfo @this, params string[] pattern);
public static IEnumerable<FileInfo> Glob(this DirectoryInfo @this, params string[] pattern)
public static Task<IEnumerable<string>> GlobRelativeAsync(this DirectoryInfo @this, params string[] pattern);
public static Task<IEnumerable<string>> GlobAbsoluteAsync(this DirectoryInfo @this, params string[] pattern);
public static Task<IEnumerable<FileInfo>> GlobAsync(this DirectoryInfo @this, params string[] pattern)

Globbing is a pattern matching technique similar to regular expressions, but simpler. The pattern is a string that may contain wildcards. You can find the supported wildcards at https://learn.microsoft.com/en-us/dotnet/core/extensions/file-globbing.

GlobRelative returns the paths of the files relative to the given directory, that match the pattern. GlobAbsolute returns the absolute paths. Glob returns the FileInfo objects of the files that match the pattern and otherwise work like GlobAbsolute. The async versions return a Task<IEnumerable<string>> and work in the same way.

var directory = new DirectoryInfo(@"/Usr/Temp");
var files = directory.GlobRelative("**/*.txt");

EnsureDirectory

public static DirectoryInfo EnsureDirectory(this DirectoryInfo directory, string path)

Like GetDirectory, but creates the directory if it does not exist.

var directory = new DirectoryInfo(@"C:\Temp");
var subDirectory = directory.EnsureDirectory("SubDirectory");

EnsureEmptyDirectory

public static DirectoryInfo EnsureEmptyDirectory(this DirectoryInfo @this, string? subPath = null)

Like EnsureDirectory, but deletes the directory if it exists and creates a new empty directory.

var directory = new DirectoryInfo(@"C:\Temp");
var subDirectory = directory.EnsureEmptyDirectory("SubDirectory");

CopyToAsync

public static async Task<DirectoryInfo> CopyToAsync(this DirectoryInfo @this, DirectoryInfo target, bool overwrite = true)
public static async Task<DirectoryInfo> CopyToAsync(this DirectoryInfo @this, string target, bool overwrite = true)
public static async Task<DirectoryInfo> CopyToAsync(this DirectoryInfo @this, DirectoryInfo target, string subPath, bool overwrite = true)

Copies the directory to the specified target directory. If the target directory does not exist, it is created. If overwrite is true, the files that already exist in the target directory are overwritten. Otherwise, they are skipped.

The second overload takes a string as target path.

The third overload copies the directory to a subdirectory of the target directory.

var directory = new DirectoryInfo(@"C:\Temp");
var target = new DirectoryInfo(@"C:\Target");
var subDirectory = await directory.CopyToAsync(target, true);

CopyToEmptyAsync

public static async Task<DirectoryInfo> CopyToEmptyAsync(this DirectoryInfo @this, DirectoryInfo target) {
public static async Task<DirectoryInfo> CopyToEmptyAsync(this DirectoryInfo @this, string target) {
public static async Task<DirectoryInfo> CopyToEmptyAsync(this DirectoryInfo @this, DirectoryInfo target, string subPath) {

Like CopyToAsync, but deletes the target directory if it exists and creates a new empty directory.

var directory = new DirectoryInfo(@"C:\Temp");
var target = new DirectoryInfo(@"C:\Target");
var subDirectory = await directory.CopyToEmptyAsync(target);

DeserializeAsync

public static T? Deserialize<T>(this DirectoryInfo @this, string fileName, JsonSerializerOptions? options = null)
public static async Task<T?> DeserializeAsync<T>(this DirectoryInfo @this, string fileName, JsonSerializerOptions? options = null)

Deserializes the json content of the file to an object of type T. The async version runs asynchronously.

var directory = new DirectoryInfo(@"C:\Temp");
var data = await directory.DeserializeAsync<MyData>("file.json");

UniqueFileInfo

public static FileInfo UniqueFileInfo(this DirectoryInfo @this, string? fileName = null)

Returns a FileInfo object for a file in the directory with a unique name. If the filename is "base.ext" the function will return a FileInfo object for a file with the name "base_n.ext", that does no yet exist in the directory and where n is a number starting at 1.

For example directory.UniqueFileInfo("file.bak") will return a FileInfo object for a file with the name lik "file_1.bak".

Warning: The function may fail if parallel processes are creating files with the same base name in the same directory.

var directory = new DirectoryInfo(@"C:\Temp");
var file = directory.UniqueFileInfo("file.txt");

SymbolicLinkTo

public static DirectoryInfo SymbolicLinkTo(this DirectoryInfo fi, string destination, bool overwrite = true) {
public static DirectoryInfo SymbolicLinkTo(this DirectoryInfo fi, FileInfo destination, bool overwrite = true) {

Creates a symbolic link to the directory. The link is created at the specified destination. If the destination already exists, the function throws an exception, unless overwrite is true.

var directory = new DirectoryInfo(@"C:\Temp\dir");
var link = directory.SymbolicLinkTo(@"C:\Target\dir");

FileInfo Extensions

CopyToAsync

public static async Task<FileInfo> CopyToAsync(this FileInfo @this, FileInfo target, bool overwrite = true) {
public static async Task<FileInfo> CopyToAsync(this FileInfo @this, string target, bool overwrite = true) {

Simple overloads of the CopyTo method of the FileInfo class that run asynchronously.

var file = new FileInfo(@"C:\Temp\file.txt");
var target = new FileInfo(@"C:\Target\file.txt");
var copiedFile = await file.CopyToAsync(target, true);

DeserializeAsync

public static T? Deserialize<T>(this FileInfo @this, JsonSerializerOptions? options = null)
public static async Task<T> DeserializeAsync<T>(this FileInfo @this, JsonSerializerOptions? options = null)

Deserializes the json content of the file to an object of type T. The async version runs asynchronously.

var file = new FileInfo(@"C:\Temp\file.json");
var data = await file.DeserializeAsync<MyData>();

SerializeAsync

public static async Task SerializeAsync<T>(this FileInfo @this, T data, JsonSerializerOptions? options = null)

Serializes the object to json and writes it to the file.

var file = new FileInfo(@"C:\Temp\file.json");
var data = new MyData();
await file.SerializeAsync(data);

ExtractTo

public static Task ExtractToAsync(this FileInfo fi, DirectoryInfo target, bool overwrite = true)
public static void ExtractTo(this FileInfo fi, DirectoryInfo target, bool overwrite = true)

Extracts the ZIP file to the specified target directory. If the target directory does not exist, it is created. If overwrite is true, the files that already exist in the target directory are overwritten. Otherwise, they are skipped. The async version runs asynchronously.

var file = new FileInfo(@"C:\Temp\archive.zip");
var target = new DirectoryInfo(@"C:\Target");
file.ExtractTo(target, true);

SymbolicLinkTo

public static FileInfo SymbolicLinkTo(this FileInfo fi, string destination, bool overwrite = true) {
public static FileInfo SymbolicLinkTo(this FileInfo fi, FileInfo destination, bool overwrite = true) {

Creates a symbolic link to the file. The link is created at the specified destination. If the destination already exists, the function throws an exception, unless overwrite is true.

var file = new FileInfo(@"C:\Temp\file.txt");
var link = file.SymbolicLinkTo(@"C:\Target\file.txt");

Write Functions

public static FileInfo WriteAllText(this FileInfo fi, string? text)
public static FileInfo WriteAllText(this FileInfo fi, string? text, Encoding e)
public static async Task<FileInfo> WriteAllTextAsync(this FileInfo fi, string? text, CancellationToken ct = default)
public static async Task<FileInfo> WriteAllTextAsync(this FileInfo fi, string? text, Encoding e, CancellationToken ct = default)
public static FileInfo WriteAllBytes(this FileInfo fi, byte[] bytes)
public static async Task<FileInfo> WriteAllBytesAsync(this FileInfo fi, byte[] bytes, CancellationToken ct = default)
public static FileInfo WriteAllLines(this FileInfo fi, IEnumerable<string> lines)
public static FileInfo WriteAllLines(this FileInfo fi, IEnumerable<string> lines, Encoding e)
public static async Task<FileInfo> WriteAllLinesAsync(this FileInfo fi, IEnumerable<string> lines, CancellationToken ct = default)
public static async Task<FileInfo> WriteAllLinesAsync(this FileInfo fi, IEnumerable<string> lines, Encoding e, CancellationToken ct = default)

These are small wrappers around the corresponding methods of the File class.

var file = new FileInfo(@"C:\Temp\file.txt");
await file.WriteAllTextAsync("Hello World!");

ControlledDirectory

The ControlledDirectory class makes sure that a directory is deleted when the object is disposed. It is useful if you want to make sure that a directory is deleted after a test or a test run.

using var directory = new ControlledDirectory(new DirectoryInfo(@"C:\Temp"));

The ControlledDirectory class has the member functions

  • DirectoryInfo: Returns the DirectoryInfo object of the directory.
  • FullName: Returns the full name of the directory.

It also has implicit conversion operators to DirectoryInfo and string.

using var directory = new ControlledDirectory(@"C:\Temp");
var fileName = Path.Combine(directory, "file.txt");
File.WriteAllText(fileName, "Hello World!");

TemporaryDirectory

The TemporaryDirectory class creates a temporary directory that is deleted when the object is disposed. It is useful if you want to create a temporary directory for a test or a test run.

using var directory = new TemporaryDirectory();

It is otherwise identical to the ControlledDirectory class. You can specify an extension for the temporary directory.

using var directory = new TemporaryDirectory(".tmp");

FileLockFactory

The FileLockFactory is used for locks in the file system with a classical lock file. Use it like this:

var factory = new FileLockFactory();
...
using var fileLock = factory.Create(lockFile, TimeSpan.FromMinutes(5))
{
...
}
Product Compatible and additional computed target framework versions.
.NET net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.1-rc.1 82 9/4/2023
1.0.0 156 8/30/2023
1.0.0-rc.1 77 8/30/2023
1.0.0-rc.0 81 8/29/2023
0.0.3-rc.6 84 8/23/2023
0.0.3-rc.4 69 8/23/2023
0.0.3-rc.3 66 8/23/2023
0.0.3-rc.2 67 8/23/2023
0.0.3-rc.1 55 8/22/2023
0.0.3-rc.0 61 8/22/2023
0.0.2 135 8/22/2023
0.0.2-rc.2 67 8/22/2023
0.0.2-rc.1 68 8/22/2023
0.0.2-rc.0 70 8/21/2023
0.0.1.8 136 8/21/2023
0.0.1.3 141 8/21/2023
0.0.1-rc.0 70 8/21/2023

Version 0.0.3
- Added asynchronous deserialize to DirectoryInfoExtensions and FileInfoExtensions
- Added ExtractTo method to FileInfoExtensions
- Added SymbolicLinkTo method to DirectoryInfoExtensions and FileInfoExtensions
- Added unit tests
- Removed overwrite parameter from CopyToEmptyAsync
- Added ControlledDirectory and TemporaryDirectory classes