release: Version 0.2.0 mit Statistiken und CHANGELOG
- Version erhöht von 0.1.0 auf 0.2.0 - CHANGELOG.md hinzugefügt mit vollständiger Feature-Liste - Statistiken am Ende: Verarbeitete/geplante/umbenannte Dateien - Fehler-Zähler für übersprungene/fehlgeschlagene Umbenennungen - Kommentar-Klarstellung in sanitizer.rs - Bessere Fehlerbehandlung mit detaillierten Error-Messages Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
fee28fa213
commit
bcbd64fd91
6 changed files with 88 additions and 15 deletions
42
CHANGELOG.md
Normal file
42
CHANGELOG.md
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [0.2.0] - 2025-02-10
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- **CLI**: `--dry-run` as primary option (with `--no-changes` as deprecated alias for backward compatibility)
|
||||||
|
- **CLI**: `--special` flag to process symlinks and special files (normally skipped)
|
||||||
|
- **Smart Default Excludes**: Automatically ignore `.git`, `.svn`, `node_modules`, `.cache`, `__pycache__`
|
||||||
|
- **Double Extensions**: Proper handling of `.tar.gz`, `.tar.bz2`, `.tar.xz`, `.tar.zst`, `.tar.lz`, `.tar.Z`
|
||||||
|
- **Parallel Processing**: Using `rayon` for parallel filename cleaning when processing ≥100 files
|
||||||
|
- **Write Permission Checks**: Check write permissions before attempting rename operations
|
||||||
|
- **Unit Tests**: 9 comprehensive tests for `clean_filename()` covering edge cases
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- **Critical Bug**: Hidden files (like `.gitignore`) are no longer incorrectly renamed to `unnamed.xxx`
|
||||||
|
- Leading dot in hidden files is now correctly preserved
|
||||||
|
- Fixed all clippy warnings
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Binary renamed from `NameToUnix` to `ntu` (shorter CLI usage)
|
||||||
|
- Improved error messages for permission issues
|
||||||
|
- Better handling of hidden files with spaces (`.my config` → `.my_config`)
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
- Parallel processing with rayon for large directory trees (threshold: 100 files)
|
||||||
|
- Optimized regex patterns using `once_cell::Lazy`
|
||||||
|
|
||||||
|
## [0.1.0] - 2025-03-07
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Initial release
|
||||||
|
- Basic filename sanitization
|
||||||
|
- Configurable replacements via TOML
|
||||||
|
- Recursive directory processing
|
||||||
|
- Exclude patterns support
|
||||||
|
- German umlaut conversion
|
||||||
|
- Special identifier preservation (C++, C#)
|
||||||
4
Cargo.lock
generated
4
Cargo.lock
generated
|
|
@ -1,10 +1,10 @@
|
||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 4
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "NameToUnix"
|
name = "NameToUnix"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"assert_fs",
|
"assert_fs",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "NameToUnix"
|
name = "NameToUnix"
|
||||||
version = "0.1.0"
|
version = "0.2.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = ["Dieter Schlüter <dieter.schlueter@linix.de>"]
|
authors = ["Dieter Schlüter <dieter.schlueter@linix.de>"]
|
||||||
description = "Ein Tool zum Anpassen von Verzeichnis- und Dateinamen an Linux-Konventionen"
|
description = "Ein Tool zum Anpassen von Verzeichnis- und Dateinamen an Linux-Konventionen"
|
||||||
|
|
|
||||||
49
src/main.rs
49
src/main.rs
|
|
@ -162,6 +162,12 @@ fn main() -> Result<()> {
|
||||||
.collect()
|
.collect()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Statistiken
|
||||||
|
let total_processed = entries.len();
|
||||||
|
let total_planned = rename_ops.len();
|
||||||
|
let mut renamed_count = 0;
|
||||||
|
let mut skipped_count = 0;
|
||||||
|
|
||||||
// Umbenennungen sequenziell ausführen
|
// Umbenennungen sequenziell ausführen
|
||||||
for op in rename_ops {
|
for op in rename_ops {
|
||||||
if let Some(bar) = &progress_bar {
|
if let Some(bar) = &progress_bar {
|
||||||
|
|
@ -176,19 +182,44 @@ fn main() -> Result<()> {
|
||||||
debug!("Rename: {:?} -> {:?}", op.old_path, op.new_path);
|
debug!("Rename: {:?} -> {:?}", op.old_path, op.new_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !args.dry_run && is_safe_rename(&op.old_path, &op.new_path, args.force) {
|
if !args.dry_run {
|
||||||
fs::rename(&op.old_path, &op.new_path).with_context(|| {
|
if is_safe_rename(&op.old_path, &op.new_path, args.force) {
|
||||||
format!(
|
match fs::rename(&op.old_path, &op.new_path) {
|
||||||
"Fehler beim Umbenennen: {} -> {}",
|
Ok(_) => renamed_count += 1,
|
||||||
op.old_path.display(),
|
Err(e) => {
|
||||||
op.new_path.display()
|
error!(
|
||||||
)
|
"Fehler beim Umbenennen: {} -> {}: {}",
|
||||||
})?;
|
op.old_path.display(),
|
||||||
|
op.new_path.display(),
|
||||||
|
e
|
||||||
|
);
|
||||||
|
skipped_count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
skipped_count += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(bar) = &progress_bar {
|
if let Some(bar) = &progress_bar {
|
||||||
bar.finish_with_message("Umbenennung abgeschlossen");
|
bar.finish_with_message("Verarbeitung abgeschlossen");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zusammenfassung ausgeben (außer im quiet mode)
|
||||||
|
if !args.quiet {
|
||||||
|
info!("");
|
||||||
|
info!("=== Zusammenfassung für {} ===", path.display());
|
||||||
|
info!("Verarbeitete Dateien/Verzeichnisse: {}", total_processed);
|
||||||
|
info!("Umbenennungen geplant: {}", total_planned);
|
||||||
|
if args.dry_run {
|
||||||
|
info!("Modus: Dry-run (keine Änderungen)");
|
||||||
|
} else {
|
||||||
|
info!("Erfolgreich umbenannt: {}", renamed_count);
|
||||||
|
if skipped_count > 0 {
|
||||||
|
info!("Übersprungen/Fehler: {}", skipped_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,12 +62,12 @@ pub fn clean_filename(name: &OsStr, config: &Config, verbose: bool) -> Option<St
|
||||||
base = preserve_special_identifiers(&base);
|
base = preserve_special_identifiers(&base);
|
||||||
ext = preserve_special_identifiers(&ext);
|
ext = preserve_special_identifiers(&ext);
|
||||||
|
|
||||||
// 1) Konfig-Replacements zuerst
|
// 1) Konfig-Replacements anwenden (zuerst)
|
||||||
for (k, v) in &config.replacements {
|
for (k, v) in &config.replacements {
|
||||||
base = base.replace(k, v);
|
base = base.replace(k, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2) Dann erst hart-codierte Ersetzungen anwenden
|
// 2) Danach hart-codierte Ersetzungen anwenden
|
||||||
base = apply_hardcoded_replacements(&base);
|
base = apply_hardcoded_replacements(&base);
|
||||||
|
|
||||||
// 3) Emojis und hochgestellte Zeichen ersetzen
|
// 3) Emojis und hochgestellte Zeichen ersetzen
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"rustc_fingerprint":16656946018727591243,"outputs":{"4614504638168534921":{"success":true,"status":"","code":0,"stdout":"rustc 1.82.0 (f6e511eec 2024-10-15)\nbinary: rustc\ncommit-hash: f6e511eec7342f59a25f7c0534f1dbea00d01b14\ncommit-date: 2024-10-15\nhost: x86_64-unknown-linux-gnu\nrelease: 1.82.0\nLLVM version: 19.1.1\n","stderr":""},"15729799797837862367":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/home/dschlueter/.rustup/toolchains/stable-x86_64-unknown-linux-gnu\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"unknown\"\nunix\n","stderr":""}},"successes":{}}
|
{"rustc_fingerprint":18315677830234863098,"outputs":{"8185672236408668984":{"success":true,"status":"","code":0,"stdout":"rustc 1.90.0 (1159e78c4 2025-09-14)\nbinary: rustc\ncommit-hash: 1159e78c4747b02ef996e55082b704c09b970588\ncommit-date: 2025-09-14\nhost: x86_64-unknown-linux-gnu\nrelease: 1.90.0\nLLVM version: 20.1.8\n","stderr":""},"11742744481059712885":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/home/dschlueter/.rustup/toolchains/stable-x86_64-unknown-linux-gnu\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"unknown\"\nunix\n","stderr":""}},"successes":{}}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue