Skip to main content

textswap

Bulk text replacement in files using dictionary mappings.

PyPI version License: GPL v3

Replace text across multiple files using find/replace dictionaries. Supports bidirectional replacement (keys-to-values or values-to-keys).

Installation

pip install textswap

Quick Start

  1. Create a config file (config.json):
{
  "dictionaries": {
    "example": {
      "old_text": "new_text",
      "foo": "bar"
    }
  },
  "ignore_extensions": [".exe", ".bin"],
  "ignore_directories": ["node_modules", ".git"],
  "ignore_file_prefixes": [".", "_"]
}
  1. Run:
textswap -f ./my_folder -d 1

Usage

# Interactive mode
textswap

# With options
textswap --folder ./src --direction 1 --config my_config.json

# Dry run (preview changes with diff output)
textswap -f ./src -d 1 --dry-run

# Back up originals before modifying
textswap -f ./src -d 1 -b ./backups

# Reverse direction (values-to-keys)
textswap -f ./src -d 2

Options

Option Short Description
--folder -f Folder to process
--direction -d 1 = keys-to-values, 2 = values-to-keys
--config -c Path to config file (default: config.json)
--dict-name -n Dictionary name (auto-selects if only one)
--backup-dir -b Copy originals here (mirroring folder structure) before modifying
--dry-run Preview changes without modifying files

Config Format

{
  "dictionaries": {
    "my_replacements": {
      "find_this": "replace_with_this",
      "old": "new"
    }
  },
  "ignore_extensions": [".exe", ".dll"],
  "ignore_directories": ["node_modules", "venv"],
  "ignore_file_prefixes": [".", "_"]
}

How It Works

  1. Load config: Reads your JSON config file containing replacement dictionaries
  2. Walk directory: Recursively traverses the target folder
  3. Filter files: Skips files matching ignore rules (extensions, prefixes, directories)
  4. Read & replace: For each file, reads content and applies all replacements from the dictionary
  5. Write back: Saves modified files (or shows diff in dry-run mode)

All files are processed as UTF-8. Non-UTF-8 files are automatically skipped with a warning.

Dry Run Output

The --dry-run flag shows exactly what would change without modifying files:

$ textswap -f ./src -d 1 --dry-run
Dry run mode - no files will be modified

Would modify: ./src/example.txt
--- a/./src/example.txt
+++ b/./src/example.txt
@@ -1 +1 @@
-Hello world
+Goodbye world

Processed 5 files, 1 modified

Multiple Dictionaries

You can define multiple dictionaries in your config for different replacement scenarios:

{
  "dictionaries": {
    "encode": {
      "secret": "s3cr3t",
      "password": "p4ssw0rd"
    },
    "localize_fr": {
      "Hello": "Bonjour",
      "Goodbye": "Au revoir"
    }
  }
}

Select which dictionary to use with --dict-name:

textswap -f ./src -d 1 -n encode
textswap -f ./src -d 1 -n localize_fr

Troubleshooting

"Invalid JSON in config file"

Your config file has a syntax error. Common issues:

  • Missing commas between items
  • Trailing commas (not allowed in JSON)
  • Unquoted strings

Use a JSON validator to check your config.

"Config must contain a 'dictionaries' object"

Your config file is missing the required dictionaries key:

{
  "dictionaries": {
    "my_dict": {"find": "replace"}
  }
}

Files being skipped

Files are skipped for these reasons (shown in output):

  • Not UTF-8 encoded: Binary files or files with different encoding
  • Permission denied: No read/write access to the file

No files modified

Check that:

  1. Your search terms exactly match the file content (case-sensitive)
  2. Files aren't being filtered by ignore rules
  3. The target folder contains text files

Replacements happening in wrong order

Replacements are applied in dictionary key order. If you have overlapping patterns (e.g., "hello" and "hello world"), the first match wins. Consider using more specific patterns.

Use Cases

  • Encoding/decoding: Obfuscate or de-obfuscate text in files
  • Localization: Batch replace text for different languages
  • Refactoring: Rename variables, functions, or classes across a codebase
  • Template substitution: Replace placeholders with actual values
  • Migration: Update deprecated API calls or import paths

Encoding

All files are read and written as UTF-8. Files that cannot be decoded as UTF-8 (binary files, files with other encodings) are automatically skipped and reported in the output.

License

GPL v3

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

textswap-0.3.0.tar.gz (29.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

textswap-0.3.0-py3-none-any.whl (23.4 kB view details)

Uploaded Python 3

File details

Details for the file textswap-0.3.0.tar.gz.

File metadata

  • Download URL: textswap-0.3.0.tar.gz
  • Upload date:
  • Size: 29.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for textswap-0.3.0.tar.gz
Algorithm Hash digest
SHA256 f17cebceb8fd38c5e9fa41e7e5bf50e7cac05f2dbfe81573cb13e38d56d99fcc
MD5 0bacc2c3c6e8935d1e75a40fdda021b7
BLAKE2b-256 2d9e1f252b8c9727b2900a265f7deee07c25c60282cc1aa870e470731d37fbbc

See more details on using hashes here.

Provenance

The following attestation bundles were made for textswap-0.3.0.tar.gz:

Publisher: publish.yml on cainky/textswap

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file textswap-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: textswap-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 23.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for textswap-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 720e10ac6719870988f1acaf3fee9570510b28c0d23d7cdc92587c603cfd14eb
MD5 284c8b3fd63118733251e41ec0d0c446
BLAKE2b-256 820ea6ab6d56b589bc5881425736104e8773229a818e2483b907bfa59ded5c98

See more details on using hashes here.

Provenance

The following attestation bundles were made for textswap-0.3.0-py3-none-any.whl:

Publisher: publish.yml on cainky/textswap

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.4.0

2 files

This release

0.3.0 This release

2 files

0.2.1

2 files

0.2.0

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page