Linux BSP Case Folding Workaround is a Linux bash script designed to resolve client-side compatibility with maps (BSP) with case folding issues with custom content in Valve Source 1 engine games on Linux, such as Half-Life 2 Deathmatch, Counter-Strike: Source, Team Fortress 2, and many others. It addresses missing textures, models, and sounds due to case sensitivity mismatches by extracting and syncing assets to the game folder, from which they are then parsed properly by the game.
- No modification to any map or game files and is completely safe to use with secure servers (zero risk of VAC ban).
- Game stability restored, reducing map-related crashes since the assets will once again be available.
BSP map files reference assets (e.g., Materials/Walls/brick01.vtf) case-insensitively, which conflicts with Linux case-sensitive filesystem (e.g., materials/walls/brick01.vtf) since the February 2025 update. This script automates bulk asset extraction, merge, and placement to ensure proper map operation.
- Automatically updates to the latest LBSPCFW and VPKEdit (for asset extraction)
- Auto-detection of compatible Steam Games (Flatpack & Snap also supported)
- Extracts custom map assets with vpkeditcli and merges them together with rsync
- Uses GNU Parallel for processing all map data, drastically reducing workload time
- Syncronization can be set to your game folder (auto-detect), or
fixfolder (manually copy contents to gamedownloadfolder) - Optionally skip previously processed maps per game using hash fingerprinting for accurate checking (new, changed, same, etc)
- Automatic configuration preset generation to streamline reprocessing of new/existing map files on a per-game basis
- Linux OS with bash version 4.0+
- Dependencies:
curl inotifywait notify-send parallel rsync unzip - Missing dependencies can be optionally be installed automatically by running the script
Manual
- To manually install dependencies, run the following command specific to your distribution:
Ubuntu/Debian-based (apt)
sudo apt update && sudo apt install curl inotify-tools libnotify-bin parallel rsync unzip -y
Arch Linux-based (pacman)
sudo pacman -Syy --noconfirm curl inotify-tools libnotify parallel rsync unzip
Fedora-based (dnf)
sudo dnf makecache && sudo dnf install curl inotify-tools libnotify parallel rsync unzip -y
Gentoo-based (portage)
sudo emerge --sync && sudo emerge -qN net-misc/curl sys-fs/inotify-tools x11-libs/libnotify sys-process/parallel net-misc/rsync app-arch/unzip
- Clone:
git clone https://github.com/scorpius2k1/linux-bsp-casefolding-workaround.git - Change to local repo folder
cd linux-bsp-casefolding-workaround - Set permissions:
chmod +x lbspcfw.sh - Run:
./lbspcfw.sh
Alternatively, clone & run with one command:
git clone https://github.com/scorpius2k1/linux-bsp-casefolding-workaround.git && cd linux-bsp-casefolding-workaround && chmod +x lbspcfw.sh && ./lbspcfw.sh
By default, the script runs with sensible defaults. However, several command-line arguments are available to customize its behavior for specific use cases. These options allow you to tailor the script for tasks such as monitoring, background services, Docker environments, and more.
The following command-line arguments are available:
--config: Load a saved game preset to quickly apply specific configurations.--docker: Execute the script within an isolated, containerized environment.--docker-rebuild: Force a fresh image build and launch the script containerized.--docker-remove: Remove the local Docker image and cleanup associated resources.--help: Display this help message and exit.--monitor: Track the active game process and apply fixes in real-time.--purge: Remove all custom assets and wipe game cache files.--reset: Reset all script data and configurations to factory defaults.--service: Deploy a background daemon for persistent, automated monitoring.--undo: Rollback via [precise] (default 1:1 list) or [recurse] (bottom-up folder purge).
NOTE: Arguments are mutually exclusive and must be used individually. The only exception is --reset, which can be followed by one additional command.
- Auto-detect:
- Run
./lbspcfw.sh(select Y to auto detect, choose game) - If you do not see your game in the list, please proceed with the manual method
- Maps already in your game folder
download/mapsare used, negating the need to copy map files
- Run
- Manual:
- Create a
bspfolder in the same folder as the script - Copy desired map files (bsp) into the
bspfolder - Run
./lbspcfw.sh(select N to auto detect) - Once the script has finished, move the contents of
fixinto gamedownloadfolder
(e.g., ../steamapps/common/Half-Life 2 Deathmatch/hl2mp/download/)
- Create a
- Presets:
- Configuration presets are automatically generated after first processing, on a per-game basis
- To use a preset, run the script normally and answer Y to the
Use configuration preset? [Y/n]prompt and choose the desired game to reprocess - Alternatively, the
--configparameter can also be passed as a command line argument./lbspcfw.sh --configto skip directly to the preset menu
LBSPCFW includes optional Docker support for running the script in a fully containerized environment.
![]()
Docker is useful if:
- Your distribution lacks compatible versions of required dependencies
- You prefer not to install additional packages on the host system
- You want a reproducible, isolated runtime
-
Run the script containerized:
./lbspcfw.sh --docker -
Rebuild the Docker image and run:
./lbspcfw.sh --docker-rebuild -
Remove the Docker image:
./lbspcfw.sh --docker-remove
When --docker is used, the script automatically builds (or reuses) the required image and executes all processing inside the container.
Important: If core script files are updated (including via auto-update), run --docker-rebuild to synchronize the container.
Docker behavior varies by system:
- Some systems require root privileges to run Docker commands
- Others allow non-root usage via membership in the docker group
Ensure Docker is installed and properly configured. If you encounter permission errors:
- Run the script with sudo, or
- Add your user to the docker group and re-login
Docker mode is intended for interactive execution only. The following features are not supported inside a container:
- Asset Purge
--purge - Asset Rollback
--undo - Configuration presets
--config - Monitoring mode
--monitor - Script data reset
--reset - Systemd service integration
--service - Steam launch command integration
lbspcfw.sh %command%
Native execution is the default and recommended method, as it’s required for full functionality and filesystem monitoring.
Docker is optional and only required when using docker flags.
- There are three options available: script runtime, systemd service, and steam which can be ran simultaneously in the background to automatically process new maps for multiple games.
-
Script
Use the--monitorargument when running the script. After processing, the monitor will automatically be started and remain running in the terminal until stopped

-
Service
To create systemd services that will automatically process maps in the background, use the--serviceargument when running the script. Services are created from existing game presets, but can also be created if none are available during initial game processing. Service status can also be checked via systemd status command for the desired game, eg.systemd status --user lbspcfw-hl2mp.service. Services are managed the same way as any other systemd service, please visit the official systemd website for specific documentation. All script systemd service monitors are placed in$HOME/.config/systemd/userwith the lbspcfw prefix.

-
Steam
Steam background monitoring can be enabled on game launch by adding/path/to/lbspcfw.sh %command%in your desired games runtime command option. Before adding to Steam, the script should be ran at least once to ensure all dependencies are available. Steam installs using snap/flatpak may not work with this option!

When using automation, it is possible that some maps may be loaded by the game before the assets can be fully extracted and synchronized, even with instantaneous script detection and implemented processing delay for new maps. If this happens, missing textures may still be present; try reconnecting to the server, restarting the game, or loading the map locally. Servers that are enforcing sv_pure can also be a factor since this typically does not allow for custom assets outside of the loaded map. In this case, a fix issued by Valve for affected games is the only option.
To work properly, all assets (materials, models, sound) extracted are required to be inside the game download folder (alternatively, they can be placed in the game root folder). Placing custom assets into the custom folder does not work since it seems to suffer the same case folding issue. This is due to the functionality of the game itself, not the script. If you require any existing custom content to be retained, please back up your existing materials/models/sound folders prior to running this script.
Asset Conflicts
The Source 1 engine lacks per-map asset isolation for external data, meaning it processes all custom assets cumulatively. While this script correctly processes these assets, the engine can encounter conflicts—particularly when a large number of maps are processed.
- Extraction Overwrites: If two or more maps utilize the same asset file path (e.g.,
materials/custom/wall.vtf) but contain different versions of that asset, the last map to be extracted will overwrite the file. Consequently, every map that references that file path will be forced to use whichever version was extracted last, leading to version mismatches. - Rendering Artifacts: As documented in #1, #7, and #14, these engine-level collisions cause textures to render incorrectly or become entirely invisible. This can result in an accidental "wall hack" effect where surfaces disappear; this is a known rendering bug within the game engine and is not a VAC-violating modification or a script error.
- Server-Side Enforcement (sv_pure): Furthermore, servers utilizing the
sv_puresetting will cause the engine to skip custom assets unless the server owner has specifically whitelisted them. Since such whitelisting is highly unlikely, any potential workaround is essentially impossible in this scenario. - Inherent Limitation: Because the engine's architecture does not allow for isolating these assets on a per-map basis, this behavior is a fundamental trait of how Source 1 handles external content and is unlikely to be resolved through any external method.
- Navigate to your game
downloadfolder and removematerialsmodelssoundfolders. If you retained any backups of these folders, be sure to restore them there afterwards. Once done, restart the game.
- A ticket for this issue is open on Valve's official Github, please follow there for updated information.
- If you find this useful and it works well for you, please ⭐ this repository and share with others in the community.
- If you would like to support my work and servers I run in the community, consider buying a coffee ☕



