Command-line interface#
The command-line interface (CLI) provides Unix-style tools for anonymizing iCalendar files from the terminal.
Installation#
First, install uv as described in Prerequisites.
Install the latest Python version and create virtual environment.
uv venv
Activate the virtual environment.
source .venv/bin/activate
.venv\Scripts\Activate.ps1
Install icalendar-anonymizer, its dependencies, and the CLI extras.
uv pip install "icalendar-anonymizer[cli]"
Verify installation with the following command.
ican --version
This should output the package name and its version number.
Commands#
Two commands are provided.
- icalendar-anonymize
Full command name
- ican
Short alias for convenience
Both commands work identically.
Usage#
This section describes how to use the command-line icalendar-anonymize application. For brevity, examples use the alias form.
The usage syntax calls the program, followed optionally by options, then input, and finally output.
ican [OPTIONS] [INPUT] [-o OUTPUT]
For a complete list of command options and field configuration options, either see Options reference or Field configuration options, or use the following command.
ican --help
Anonymize a file#
Read from a file and write to another file:
ican calendar.ics -o anonymized.ics
Verbose output with the -v option shows progress.
ican -v calendar.ics -o anonymized.ics
Write to stdout#
Omit the -o flag to write to stdout:
ican calendar.ics
Read from stdin#
Omit the input argument to read from stdin:
cat calendar.ics | ican > anonymized.ics
Field configuration#
For a complete list of supported fields, use the --help option.
ican --help
Keep summaries, remove locations.
ican --summary keep --location remove calendar.ics
Replace descriptions with placeholders.
ican --description replace calendar.ics
Combine multiple field modes.
ican --summary keep --location remove --description replace calendar.ics
Pipeline processing#
Note
PowerShell examples use the -o flag instead of >. PowerShell 5.1 encodes > as UTF-16, which corrupts the output for tools that expect UTF-8.
PowerShell 5.1 also re-encodes stdin pipes through the console code page and can mangle non-ASCII content.
For data with accents or non-Latin text on 5.1, prefer the file-argument form (ican calendar.ics -o anonymized.ics).
PowerShell 7+ handles UTF-8 through pipes correctly.
Read from a file and write to a file.
cat calendar.ics | ican > anonymized.ics
ican calendar.ics -o anonymized.ics
Read from stdin explicitly with -.
ican - < calendar.ics > anonymized.ics
PowerShell re-encodes piped bytes from stdin through the console code page.
On 5.1 this corrupts non-ASCII characters, even with -Encoding utf8.
Pass the file path directly instead.
ican calendar.ics -o anonymized.ics
Verbose output to stderr doesn’t corrupt stdout.
cat calendar.ics | ican -v > anonymized.ics
ican -v calendar.ics -o anonymized.ics
Batch processing#
Anonymize all ICS files in directory.
for file in *.ics; do
ican "$file" -o "anonymized-$file"
done
Get-ChildItem *.ics -File | ForEach-Object {
ican $_.Name -o "anonymized-$($_.Name)"
}
Process files from a list.
while read -r file; do
ican "$file" -o "anon-$(basename "$file")"
done < file-list.txt
Get-Content file-list.txt -Encoding utf8 | ForEach-Object {
$file = $_.Trim()
if ($file) {
ican $file -o "anon-$(Split-Path $file -Leaf)"
}
}
Remote files#
Download a remote file and anonymize it.
curl https://example.com/calendar.ics | ican > local-anon.ics
Invoke-WebRequest https://example.com/calendar.ics -UseBasicParsing -OutFile remote.ics
ican remote.ics -o local-anon.ics
Do the previous example with error checking.
curl -f https://example.com/calendar.ics | ican -v > local-anon.ics
try {
Invoke-WebRequest https://example.com/calendar.ics -UseBasicParsing -OutFile remote.ics -ErrorAction Stop
ican -v remote.ics -o local-anon.ics
} catch {
Write-Error $_.Exception.Message
exit 1
}
Combining with other tools#
Anonymize and count events.
ican calendar.ics | grep -c "BEGIN:VEVENT"
(ican calendar.ics | Select-String "BEGIN:VEVENT").Count
Anonymize and validate the input.
ican calendar.ics | <your-validator>
Compress the anonymized output.
ican calendar.ics | gzip > anonymized.ics.gz
Windows PowerShell doesn’t include a gzip command by default.
Anonymize to a file first, then compress it with a third-party tool such as 7-Zip.
ican calendar.ics -o anonymized.ics
& "C:\Program Files\7-Zip\7z.exe" a -tgzip anonymized.ics.gz anonymized.ics
Keep summaries for debugging, pipe to a file, and compress it.
ican --summary keep calendar.ics | gzip > debug-anon.ics.gz
ican --summary keep calendar.ics -o debug-anon.ics
& "C:\Program Files\7-Zip\7z.exe" a -tgzip debug-anon.ics.gz debug-anon.ics
Anonymization summary#
The CLI uses the same anonymization as the Python API:
See also
See Property Handling Reference for the complete property reference table.
Anonymized properties#
These properties get anonymized and hashed with SHA-256.
Event summaries, descriptions, locations
Attendee and organizer names (CN parameter)
Comments, categories, resources
UIDs (uniqueness preserved)
Preserved properties#
These properties get preserved for bug reproduction.
All dates and times (DTSTART, DTEND, DUE)
Recurrence rules (RRULE, RDATE, EXDATE)
Status, priority, sequence numbers
Timezones (complete VTIMEZONE)
Error handling#
The CLI provides error messages for common issues, as described in each of the following subsections.
File not found#
$ ican nonexistent.ics
Error: Could not open 'nonexistent.ics': No such file or directory
Exit code: 2.
Invalid ICS file#
$ echo "invalid content" | ican
Error: Invalid ICS file - Expected instance of <class 'icalendar.cal.Component'>
Exit code: 1.
Empty input#
$ echo "" | ican
Error: Input is empty
Exit code: 1.
Permission denied#
$ ican protected.ics -o /root/output.ics
Error: [Errno 13] Permission denied: '/root/output.ics'
Exit code: 1.
Keyboard interrupt#
$ ican large-file.ics
^C
Interrupted
Exit code: 130.
Exit codes#
The CLI follows Unix conventions for exit codes:
Code |
Meaning |
When used |
|---|---|---|
0 |
Success |
Anonymization completed successfully |
1 |
General error |
Invalid ICS, empty input, I/O errors, unexpected errors |
2 |
File error |
Input file not found or cannot be opened |
130 |
Interrupted |
User pressed Ctrl+C (SIGINT) |
Troubleshooting#
The following sections provide troubleshooting tips.
Command not found#
If you get command not found after installation:
Reinstall the package with the CLI extras:
uv pip install --reinstall "icalendar-anonymizer[cli]"
Use the full Python module path:
python -m icalendar_anonymizer.cli calendar.ics
Binary mode on Windows#
The CLI automatically handles binary mode on Windows. You don’t need to worry about CRLF line endings.
If you encounter encoding issues on Windows, then use binary mode with PowerShell.
Get-Content calendar.ics -Raw | ican > anonymized.ics
Large files#
The CLI loads the entire file into memory. For large files over 100MB in size, the following tips will improve performance.
Monitor memory usage. Use verbose mode to track progress.
ican -v large-file.ics -o output.ics
Use the Python API for programmatic control over memory usage.
Debugging#
Enable verbose mode with the -v option to see processing steps.
ican -v calendar.ics -o anonymized.ics
Check the exit code after running ican, according to your operating system and shell.
ican calendar.ics
echo $?
ican calendar.ics
echo %ERRORLEVEL%
ican calendar.ics
echo $LASTEXITCODE
Getting help#
If you encounter issues with the CLI:
Use
ican --helpfor usage information.Check the Issue Tracker.
Open a new issue with: - Your command - Error message - Operating system - Python version (
python --version) - Package version (ican --version)
Integration examples#
The following examples describe how to integrate icalendar-anonymizer with various third-party tools.
Git pre-commit hook#
Automatically anonymize calendars before committing:
#!/bin/bash
# .git/hooks/pre-commit
for file in *.ics; do
if [ -f "$file" ]; then
ican "$file" -o "anon-$file"
git add "anon-$file"
fi
done
cron job#
Periodically anonymize shared calendars:
# Crontab entry: Anonymize daily at 2 AM
0 2 * * * /usr/bin/ican /path/to/calendar.ics -o /path/to/anon.ics
Options reference#
- [INPUT]#
Input iCalendar file to anonymize. Optional positional argument.
Default:
stdin(-)Format: File path or
-forstdinExample:
ican calendar.ics
- -o <file>, --output <file>#
Output file for anonymized calendar.
Default:
stdout(-)Format: File path or
-forstdoutExample:
ican input.ics -o output.ics
- -v, --verbose#
Show processing information on stderr. Displays input/output sources and processing steps.
Flag: No value required
Output: Messages written to stderr (not
stdout)Example:
ican -v calendar.ics -o anonymized.ics
The following example shows verbose output:
Reading from: calendar.ics Parsing calendar... Anonymizing calendar... Writing to: anonymized.ics Done.
- --version#
Display version information and exit.
$ ican --version icalendar-anonymizer, version <version>
- --help#
Show usage information and exit.
ican --helpNote
The output for “Usage” is somewhat misleading, as Click merges
-o, --output FILENAMEwith the options instead of as a positional final optional argument. See also #148 for a related Click formatting quirk.
Field configuration options#
Configure how individual fields are anonymized.
The four modes are keep, remove, randomize, and replace.
- --summary <mode>#
Mode for SUMMARY field.
Choices:
keep,remove,randomize,replaceDefault:
randomizeExample:
ican --summary keep calendar.ics
- --description <mode>#
Mode for DESCRIPTION field.
- --location <mode>#
Mode for LOCATION field.
- --comment <mode>#
Mode for COMMENT field.
- --contact <mode>#
Mode for CONTACT field.
- --resources <mode>#
Mode for RESOURCES field.
- --categories <mode>#
Mode for CATEGORIES field.
- --attendee <mode>#
Mode for ATTENDEE field.
- --organizer <mode>#
Mode for ORGANIZER field.
- --uid <mode>#
Mode for UID field.
Note
The
removemode is not allowed.Choices:
keep,randomize,replaceDefault:
randomize
See also#
Python API - Python API for programmatic usage
Installation - Installation instructions
API Reference - Complete API reference
Contributing - Development guide