Ordnung is a Python utility for sorting YAML and JSON files alphabetically by keys. It supports batch processing, directory traversal, pattern matching, and is designed for both development and CI/CD workflows.
- π§ Automatic file type detection - Supports
.json,.yaml, and.ymlfiles (including both single-document and multi-document YAML files with---separators) - π Batch processing - Process multiple files, directories, or use glob patterns
- π Recursive sorting - Sorts nested dictionaries, lists, and complex data structures
- π― Pattern matching - Filter files with glob patterns and regex
- π« File exclusion - Exclude files matching patterns (supports glob and regex)
- β Check mode - Verify formatting without rewriting files (CI-friendly)
- π Data validation - Validate that all data structures are preserved after sorting
- π Custom indentation - Configurable indentation for both JSON and YAML
- π’ Array sorting - Optionally sort arrays of objects by first key value
- π Unicode support - Full support for international characters
- β‘ Fast and efficient - Optimized for large files and batch operations
# Install from PyPI
pip install ordnung
# Or install from source
git clone <repository-url>
cd ordnung
pip install -e .# Sort a single file (overwrites original)
ordnung config.json
ordnung settings.yaml
# Sort and save to new file
ordnung input.json -o sorted.json
# Sort multiple files
ordnung file1.json file2.yaml file3.ymlOrdnung supports both single-document YAML and multi-document YAML files (with --- separators). Each document in a multi-document YAML file will be sorted individually, and document order can be preserved or sorted using the appropriate flag.
# Sort single files
ordnung config.json
ordnung settings.yaml
# Sort multi-document YAML (all docs in file will be sorted)
ordnung multi-docs.yaml
# Sort multiple files at once
ordnung file1.json file2.yaml file3.yml
# Save to new file (only for single file input)
ordnung input.json -o sorted.json# Sort all JSON/YAML files in a directory
ordnung ./configs
# Recursively process subdirectories
ordnung ./configs --recursive
# Use glob patterns
ordnung './data/**/*.json' --pattern
ordnung './configs/*.yaml' --pattern# Filter with regex patterns
ordnung ./mydir --regex '.*\.ya?ml$'
ordnung ./data --regex '.*_prod\.json$'
ordnung ./configs --regex '.*_config\.ya?ml$'
# Combine recursive search with regex
ordnung ./data --recursive --regex '.*\.json$'# Exclude files matching patterns
ordnung ./data --exclude '*.tmp' --exclude 'backup_*'
ordnung ./configs --exclude '.*\.bak$' --recursive
# Exclude with multiple patterns
ordnung ./data --exclude '*.tmp' --exclude '*.bak' --exclude 'backup_*'
# Combine exclusion with other filters
ordnung ./data --exclude '*.tmp' --regex '.*\.json$' --recursive# Check mode: verify formatting without modifying files
ordnung ./data --check
# Use in CI pipeline (exits with error if files need formatting)
ordnung ./configs --recursive --check# Validate data preservation during sorting
ordnung config.json --validate
ordnung ./data --validate --recursive
# Combine validation with other options
ordnung ./configs --validate --exclude '*.tmp' --recursive
# Use validation in CI/CD pipelines
ordnung ./data --validate --check --recursive# Custom indentation
ordnung config.json --json-indent 4
ordnung settings.yaml --yaml-indent 4
# Sort arrays of objects by first key value
ordnung data.json --sort-arrays-by-first-key# Verbose logging
ordnung config.json --log-level DEBUG
# Quiet mode
ordnung config.json --log-level ERROR| Option | Description | Example |
|---|---|---|
inputs |
Input file(s), directory(ies), or glob pattern(s) | config.json |
-o, --output |
Output file path (single file only) | -o sorted.json |
--json-indent |
JSON indentation spaces (default: 2) | --json-indent 4 |
--yaml-indent |
YAML indentation spaces (default: 2) | --yaml-indent 4 |
--recursive |
Recursively search directories | --recursive |
--pattern |
Treat inputs as glob patterns | --pattern |
--regex |
Filter files with regex | --regex '.*\.json$' |
--exclude |
Exclude files matching pattern (can be used multiple times) | --exclude '*.tmp' |
--validate |
Validate that all data structures are preserved after sorting | --validate |
--check |
Check formatting without modifying | --check |
--sort-arrays-by-first-key |
Sort arrays by first key value | --sort-arrays-by-first-key |
--sort-docs-by-first-key |
For YAML files with multiple documents (--- separated), sort documents by the type and string value of the first key's value in each document, for robust and deterministic ordering. Documents with string values come before int, then float, then dict, then list, etc. For example: all docs whose first key is a string value are first, then int, then dict, then list. | --sort-docs-by-first-key |
--log-level |
Set logging level | --log-level DEBUG |
Input JSON:
{
"zebra": "striped animal",
"apple": "red fruit",
"settings": {
"theme": "dark",
"language": "en"
}
}Output JSON:
{
"apple": "red fruit",
"settings": {
"language": "en",
"theme": "dark"
},
"zebra": "striped animal"
}Input (with --sort-arrays-by-first-key):
{
"users": [
{"name": "Charlie", "id": 3},
{"name": "Alice", "id": 1},
{"name": "Bob", "id": 2}
]
}Output:
{
"users": [
{"name": "Alice", "id": 1},
{"name": "Bob", "id": 2},
{"name": "Charlie", "id": 3}
]
}The --validate option ensures that all data structures, keys, and values are preserved during sorting. This is particularly useful for critical configuration files where data integrity is paramount.
What gets validated:
- β All dictionary keys are preserved
- β All array elements are preserved (order may change)
- β All nested structures are intact
- β Data types remain consistent
- β Values are unchanged
Example validation output:
$ ordnung config.json --validate
INFO: Detected file type: JSON
INFO: Loaded data from: config.json
INFO: Data sorted successfully
INFO: Validating data preservation...
INFO: Data validation passed - all structures preservedIf validation fails:
$ ordnung config.json --validate
ERROR: Data validation failed! The following issues were found:
ERROR: Missing keys at root: ['important_key']
ERROR: Value mismatch at settings.debug: true vs false
ERROR: Data validation failed - data structures were not preserved during sorting# Run all tests
pytest
# Run with coverage
pytest --cov=src/ordnung
# Run specific test categories
pytest tests/test_dedicated.py
pytest tests/test_file_sorter.pyordnung/
βββ src/
β βββ ordnung/
β βββ __init__.py
β βββ file_sorter.py
βββ tests/
β βββ conftest.py # Shared test helpers
β βββ test_file_sorter.py # Auto-generated file-based tests
β βββ test_dedicated.py # Dedicated scenario tests
β βββ data/
β βββ pass/ # Valid test files
β βββ fail/ # Invalid test files
βββ pyproject.toml
βββ README.md
# Clone repository
git clone <repository-url>
cd ordnung
# Install in development mode
pip install -e .
# Install development dependencies
pip install -e ".[dev]"
# Run linting
ruff check .
# Run tests
pytestContributions are welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Add or update tests
- Run the test suite (
pytest) - Ensure code quality (
ruff check .) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow PEP 8 style guidelines
- Use ruff for linting and formatting
- Write comprehensive tests for new features
- Update documentation as needed
This project is licensed under the Apache License, Version 2.0 - see the LICENSE file for details.
- Built with PyYAML for YAML processing
- Uses ruff for code quality
- Inspired by the need for consistent configuration file formatting
Ordnung - Bringing order to your configuration files! π―
