Skip to content

DreamWeave-MP/vfstool

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

382 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

vfstool

vfstool is a command-line utility for interacting with OpenMW's virtual file system (VFS). It allows users to locate files, serialize the VFS to various formats, extract files, and even collapse the VFS into a single directory for space savings, and to reuse OpenMW's feature set for other games.

Features

  • Collapse the VFS: Create a set of hardlinks or symbolic links for the entire VFS in a target directory.
  • Extract Files: Extract specific files from the VFS to a given directory.
  • Find Files: Locate files in the VFS by name, extension, or other criteria.
  • Serialize the VFS: Output the VFS structure in JSON, YAML, or TOML formats.
  • Filter Remaining Files: Identify files in a directory that are replaced or not replaced by the VFS.
  • Conflict and provider reports: Inspect winners, fully shadowed sources, duplicates, archives, per-source contributions, and source-to-source diffs.
  • Lock/drift checks: Emit a deterministic winner manifest and compare later VFS state against it.
  • Run tools against a merged VFS: Dump a merged tree, execute a child command, then capture new or modified output files.

Installation

As of version 1.0, vfstool is published in many places.

GitHub

The latest stable release can be downloaded from GitHub for macOS, Linux, and Windows here. Development builds can be found here.

AUR

yay -S vfstool-git.

crates.io

cargo install vfstool

source

Clone the repository and build the tool using cargo:

git clone https://github.com/DreamWeave-MP/vfstool.git
cd vfstool
cargo install --path vfstool

1.0 breaking API changes for Rust consumers

The vfstool CLI keeps the same user-facing archive behavior, but the library API was cleaned up for 1.0. If you depend on vfstool_lib directly, check these before upgrading:

  • VFS keys are byte-first normalized resource paths now. Use vfstool_lib::NormalizedPath and VfsKeyInput for VFS keys; keep using Path/PathBuf for real host filesystem paths. These are not the same thing, despite many older APIs pretending they were. They were lying.
  • Bethesda archive support is provided by dream_archive; enable it with the beth-archives feature. The old bsa feature name is gone because the feature covers both BSA and BA2.
  • vfstool_lib re-exports serde, serde_json, serde_yaml, and toml when serialize is enabled, so applications can share the library's serialization stack instead of pinning duplicate parser versions.
  • ZIP/PK3 support uses zip without default features. Currently supported ZIP compression is stored, deflate, and LZMA; AES, bzip2, PPMd, deflate64, and zstd are intentionally not dragged into the dependency graph.

Usage

vfstool [OPTIONS] <COMMAND>

Global Options

  • -c, --config <CONFIG>: Path to the directory containing openmw.cfg. If omitted, the system default location is used. For a config file with a nonstandard name, set OPENMW_CONFIG to the absolute file path instead.
  • -r, --use-relative: Use relative paths in output.
  • -h, --help: Describe usage of the app or any subcommand

Commands

collapse

Collapse the VFS into a target directory using hardlinks, symbolic links, or file copies.

vfstool collapse [OPTIONS] <COLLAPSE_INTO>

Options:

  • <COLLAPSE_INTO>: Target folder to collapse the VFS into.
  • -a, --allow-copying: Fall back to copying files if linking fails.
  • -e, --extract-archives: Extract files from BSA/BA2 archives during collapsing.
  • -s, --symbolic: Use symbolic links instead of hardlinks.
  • --dry-run: Print the planned materialization actions instead of writing files.
  • -f, --format <FORMAT>: Output format for --dry-run (json, yaml, or toml). Default: yaml.
  • -o, --output <OUTPUT>: Path to save the --dry-run plan. If omitted, results are printed to stdout.

extract

Extract a specific file from the VFS into a target directory.

vfstool extract <SOURCE_FILE> <TARGET_DIR>

Arguments:

  • <SOURCE_FILE>: Full relative path to a VFS file (e.g., meshes/xbase_anim.nif).
  • <TARGET_DIR>: Directory to extract the file to.

find-file

Locate a specific file in the VFS and return its absolute or relative path.

vfstool find-file [OPTIONS] <PATH>

Arguments:

  • <PATH>: Full (relative) VFS path to query.

Options:

  • -p, --only_physical: Match only loose files; exits 2 if the file exists only in an archive.
  • -s, --simple: Output the result in a simple format (no colors or formatting).

find

Search for files in the VFS using a case-insensitive regular expression matched against normalized VFS paths.

vfstool find [OPTIONS] <PATH>

Arguments:

  • <PATH>: Case-insensitive regex matched against VFS paths.

Options:

  • -f, --format <FORMAT>: Output format (json, yaml, or toml). Default: yaml.
  • -o, --output <OUTPUT>: Path to save the search results. If omitted, results are printed to stdout.

remaining

Filter the VFS to show files replacing or not replacing contents of a given directory.

vfstool remaining [OPTIONS] <FILTER_PATH>

Arguments:

  • <FILTER_PATH>: Configured data directory to filter against.

Options:

  • -r, --replacements-only: Show only files replacing contents of the given path.
  • -f, --format <FORMAT>: Output format (json, yaml, or toml). Default: yaml.
  • -o, --output <OUTPUT>: Path to save the filtered VFS. If omitted, results are printed to stdout.

conflicts

Report source override relationships across the load order.

vfstool conflicts [OPTIONS]

Options:

  • -f, --format <FORMAT>: Output format (json, yaml, or toml). Default: yaml.
  • -o, --output <OUTPUT>: Path to save the report. If omitted, results are printed to stdout.

shadowed

Report sources whose files are all overridden by higher-priority sources. By default this is a summary; use -l, --list-files to include every overridden file.

vfstool shadowed [OPTIONS]

Options:

  • -f, --format <FORMAT>: Output format (json, yaml, or toml). Default: yaml.
  • -o, --output <OUTPUT>: Path to save the report. If omitted, results are printed to stdout.
  • -l, --list-files: Include per-source overridden file lists.

Provider reports

Inspect the provider index used by the resolved VFS. These commands are projections over the same VFS provider data; they are not a second conflict system wearing a fake moustache.

vfstool explain [OPTIONS] <PATH>
vfstool duplicates [OPTIONS] [PATTERN]
vfstool archives [OPTIONS]
vfstool archive-list [OPTIONS] <ARCHIVE>
vfstool contributions [OPTIONS]
vfstool validate [OPTIONS]

Commands:

  • explain <PATH>: Show the winning provider and lower-priority providers for one VFS key.
  • duplicates [PATTERN]: List VFS keys with more than one provider. PATTERN, when supplied, is a case-insensitive regex over normalized VFS keys, e.g. ^meshes/ or textures/.*\\.dds$.
  • archives: List loaded archives and how many entries currently win.
  • archive-list <ARCHIVE>: List VFS entries supplied by one archive.
  • contributions: Report per-source provider counts, wins, overridden files, unique files, and duplicates.
  • validate: Report missing data=, fallback-archive=, content=, and groundcover= entries from openmw.cfg.

Options:

  • -f, --format <FORMAT>: Output format (json, yaml, or toml). Default: yaml.
  • -o, --output <OUTPUT>: Path to save the report. If omitted, results are printed to stdout.

diff

Compare files between two configured data directories.

vfstool diff [OPTIONS] <SOURCE_A> <SOURCE_B>

Arguments:

  • <SOURCE_A>: First configured data directory to compare.
  • <SOURCE_B>: Second configured data directory to compare.

Options:

  • -f, --format <FORMAT>: Output format (json, yaml, or toml). Default: yaml.
  • -o, --output <OUTPUT>: Path to save the report. If omitted, results are printed to stdout.

run

Dump the merged VFS to a directory, run a child command, then capture new or modified files to data-local or --output.

vfstool run [OPTIONS] <MERGED_DIR> -- <COMMAND>...

Options:

  • --keep-merged: Keep the merged directory after the child command exits.
  • --output <OUTPUT>: Destination for captured files. Defaults to data-local from openmw.cfg.
  • --copy: Copy files instead of hardlinking them into the merged directory.
  • --working-dir <WORKING_DIR>: Working directory for the child process.

{} in child command arguments is replaced with the merged directory path. Deletions made by the child command are not captured.

<MERGED_DIR> must be absent or empty; run refuses to delete a non-empty directory. If the child process starts successfully, vfstool run returns the child process exit code. Exit code 9 is reserved for setup, spawn, or capture failures in vfstool itself.

By default, run uses hardlinks when dumping loose files into the merged directory. This avoids duplicating data, but child tools that modify files in place may modify the original loose source files through those hardlinks. Use --copy for tools that are not hardlink-safe. No, that is not a theoretical footgun. It is just how hardlinks work.


lock

Emit a deterministic lock manifest for current VFS winners.

vfstool lock [OPTIONS]

Options:

  • -f, --format <FORMAT>: Output format (json, yaml, or toml). Default: yaml.
  • -o, --output <OUTPUT>: Path to save the lock file. If omitted, results are printed to stdout.

drift

Compare the current VFS state to a lock manifest.

vfstool drift [OPTIONS] <LOCK_FILE>

Options:

  • --fail-on-drift: Exit with code 4 when drift is detected.
  • -f, --format <FORMAT>: Output format (json, yaml, or toml). Default: yaml.
  • -o, --output <OUTPUT>: Path to save the report. If omitted, results are printed to stdout.

Exit codes

vfstool uses nonzero exit codes for machine-readable failure cases:

Code Meaning
1 find-file did not find the requested VFS path
2 find-file --only_physical found the path only inside an archive
4 drift --fail-on-drift detected drift
5 validate found load-order/configuration problems
6 invalid regular expression
7 failed to load openmw.cfg
8 invalid input, such as an unknown source path
9 runtime failure while reading, writing, materializing, or starting/capturing a child command

run passes through the child process exit code after the child starts successfully.


Examples

The published rustdoc for the vfstool binary also contains operational examples for configuration, provider inspection, lock/drift, collapse previews, and run. The README is the quick path; rustdoc is the self-documenting reference we try not to let rot.

Collapse the VFS into a directory with symlinks

vfstool collapse -s /path/to/target

This form is the most space-efficient variant of collapse, since it doesn't copy or extract files. It's fragile and most ideal for testing mods.

Collapse the VFS into a single directory, with extraction and hardlinks

vfstool -c C:\Games\Oblivion collapse -ae C:\Games\Oblivion\Data

This form consumes more space and takes longer due to extracting archive contents, but will perform better ingame and allow removing BSAs entirely.

Extract a file from the VFS

vfstool extract meshes/xbase_anim.nif /path/to/output

Find a file in the VFS

vfstool find-file meshes/xbase_anim.nif

Search for files by extension

vfstool find -f json -o results.json '[.]nif$'

Show files replacing contents of a directory

vfstool remaining -r /path/to/filter

Run a tool against a merged VFS

vfstool run /tmp/merged -- some-tool {} output.txt

Explain why a file resolves to its winner

vfstool explain textures/tx_bc_mudcrab.dds

See which sources contribute winners or get overridden

vfstool contributions -f json -o contributions.json

Validate the provider index before materializing

vfstool validate

Preview a collapse without writing files

vfstool collapse --dry-run -f yaml /tmp/merged-preview

Lock current winners and fail later if they drift

vfstool lock -o vfs-lock.yaml
vfstool drift --fail-on-drift vfs-lock.yaml

License

This project is licensed under the GNU General Public License v3.0.


About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors