neue Optionen (-r, Installskript) installiert
This commit is contained in:
parent
0bab728d62
commit
d78e318d8a
15 changed files with 273 additions and 42 deletions
26
CHANGELOG.md
26
CHANGELOG.md
|
|
@ -5,6 +5,32 @@ 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/),
|
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).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [1.0.0] - 2025-02-10
|
||||||
|
|
||||||
|
### ⚠️ BREAKING CHANGES
|
||||||
|
- **Recursion is now opt-in**: By default, `ntu` only processes the specified
|
||||||
|
paths and their immediate children. Use `-r`/`--recursive` flag to enable
|
||||||
|
recursive directory traversal.
|
||||||
|
- Migration: Add `-r` to existing commands to preserve v0.x behavior
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- **`--conf <FILE>` option**: Specify a single configuration file, bypassing
|
||||||
|
the default hierarchy (/etc → ~/.config → ./). Errors if file doesn't exist.
|
||||||
|
- **`-r/--recursive` flag**: Enable recursive directory processing
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Default behavior is now non-recursive (use `-r` for recursive processing)
|
||||||
|
- All integration tests updated to explicitly use `-r` flag
|
||||||
|
|
||||||
|
### Migration Guide
|
||||||
|
```bash
|
||||||
|
# Old command (v0.x - always recursive):
|
||||||
|
ntu /path/to/files
|
||||||
|
|
||||||
|
# New equivalent (v1.x - explicit recursion):
|
||||||
|
ntu -r /path/to/files
|
||||||
|
```
|
||||||
|
|
||||||
## [0.3.0] - 2025-02-10
|
## [0.3.0] - 2025-02-10
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
|
||||||
2
Cargo.lock
generated
2
Cargo.lock
generated
|
|
@ -4,7 +4,7 @@ version = 4
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "NameToUnix"
|
name = "NameToUnix"
|
||||||
version = "0.3.0"
|
version = "1.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"assert_cmd",
|
"assert_cmd",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "NameToUnix"
|
name = "NameToUnix"
|
||||||
version = "0.3.0"
|
version = "1.0.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"
|
||||||
|
|
|
||||||
60
README.md
60
README.md
|
|
@ -27,6 +27,18 @@ Dies ist mein erstes Programm in Rust. (Bitte seid gnädig.)
|
||||||
|
|
||||||
(c) 2025 Dieter Schlüter <dieter.schlueter@linix.de>
|
(c) 2025 Dieter Schlüter <dieter.schlueter@linix.de>
|
||||||
|
|
||||||
|
## ⚠️ BREAKING CHANGE in v1.0.0
|
||||||
|
|
||||||
|
**Recursion is now opt-in**: As of version 1.0.0, `ntu` processes only the
|
||||||
|
specified paths and their immediate children by default. Use the `-r` or
|
||||||
|
`--recursive` flag to enable recursive directory traversal.
|
||||||
|
|
||||||
|
**Migration**: Add `-r` to your existing commands:
|
||||||
|
```bash
|
||||||
|
# Old (v0.x): ntu /path/to/files
|
||||||
|
# New (v1.x): ntu -r /path/to/files
|
||||||
|
```
|
||||||
|
|
||||||
## Functions / Funktionen
|
## Functions / Funktionen
|
||||||
|
|
||||||
- Replaces spaces and special characters in file and directory names with underscores
|
- Replaces spaces and special characters in file and directory names with underscores
|
||||||
|
|
@ -103,30 +115,36 @@ sudo mandb # Update man database
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Basic usage
|
# Basic usage (non-recursive: only immediate children)
|
||||||
ntu /path/to/files
|
ntu /path/to/files
|
||||||
|
|
||||||
|
# Recursive processing (process subdirectories)
|
||||||
|
ntu -r /path/to/files
|
||||||
|
|
||||||
# Dry-run: only preview the changes without actual renaming
|
# Dry-run: only preview the changes without actual renaming
|
||||||
ntu --dry-run /path/to/files
|
ntu --dry-run -r /path/to/files
|
||||||
ntu -n /path/to/files # Short form
|
ntu -n -r /path/to/files # Short form
|
||||||
|
|
||||||
|
# Use specific config file
|
||||||
|
ntu --conf /path/to/custom.toml /path/to/files
|
||||||
|
|
||||||
# Process multiple paths
|
# Process multiple paths
|
||||||
ntu /path1 /path2 /path3
|
ntu -r /path1 /path2 /path3
|
||||||
|
|
||||||
# Exclude specific files
|
# Exclude specific files
|
||||||
ntu -e "*.tmp" -e "backup_*" /path/to/files
|
ntu -r -e "*.tmp" -e "backup_*" /path/to/files
|
||||||
|
|
||||||
# Process symlinks and special files (normally skipped)
|
# Process symlinks and special files (normally skipped)
|
||||||
ntu --special /path/to/files
|
ntu -r --special /path/to/files
|
||||||
|
|
||||||
# Increase verbosity
|
# Increase verbosity
|
||||||
ntu -v /path/to/files
|
ntu -r -v /path/to/files
|
||||||
|
|
||||||
# Also rename the root directory
|
# Also rename the root directory
|
||||||
ntu --modify-root /path/to/files
|
ntu -r --modify-root /path/to/files
|
||||||
|
|
||||||
# Combine options
|
# Combine options
|
||||||
ntu --dry-run -v --special /path/to/files
|
ntu --dry-run -r -v --special /path/to/files
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -136,30 +154,36 @@ ntu --dry-run -v --special /path/to/files
|
||||||
## Verwendung
|
## Verwendung
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Grundlegende Verwendung
|
# Grundlegende Verwendung (nicht-rekursiv: nur direkte Kinder)
|
||||||
ntu /pfad/zu/dateien
|
ntu /pfad/zu/dateien
|
||||||
|
|
||||||
|
# Rekursive Verarbeitung (Unterverzeichnisse verarbeiten)
|
||||||
|
ntu -r /pfad/zu/dateien
|
||||||
|
|
||||||
# Dry-run: Nur Vorschau der Änderungen ohne tatsächliche Umbenennung
|
# Dry-run: Nur Vorschau der Änderungen ohne tatsächliche Umbenennung
|
||||||
ntu --dry-run /pfad/zu/dateien
|
ntu --dry-run -r /pfad/zu/dateien
|
||||||
ntu -n /pfad/zu/dateien # Kurzform
|
ntu -n -r /pfad/zu/dateien # Kurzform
|
||||||
|
|
||||||
|
# Spezifische Config-Datei verwenden
|
||||||
|
ntu --conf /pfad/zu/custom.toml /pfad/zu/dateien
|
||||||
|
|
||||||
# Mehrere Pfade verarbeiten
|
# Mehrere Pfade verarbeiten
|
||||||
ntu /pfad1 /pfad2 /pfad3
|
ntu -r /pfad1 /pfad2 /pfad3
|
||||||
|
|
||||||
# Bestimmte Dateien ausschließen
|
# Bestimmte Dateien ausschließen
|
||||||
ntu -e "*.tmp" -e "backup_*" /pfad/zu/dateien
|
ntu -r -e "*.tmp" -e "backup_*" /pfad/zu/dateien
|
||||||
|
|
||||||
# Symlinks und Special Files verarbeiten (normalerweise übersprungen)
|
# Symlinks und Special Files verarbeiten (normalerweise übersprungen)
|
||||||
ntu --special /pfad/zu/dateien
|
ntu -r --special /pfad/zu/dateien
|
||||||
|
|
||||||
# Verbosity erhöhen
|
# Verbosity erhöhen
|
||||||
ntu -v /pfad/zu/dateien
|
ntu -r -v /pfad/zu/dateien
|
||||||
|
|
||||||
# Auch das Wurzelverzeichnis umbenennen
|
# Auch das Wurzelverzeichnis umbenennen
|
||||||
ntu --modify-root /pfad/zu/dateien
|
ntu -r --modify-root /pfad/zu/dateien
|
||||||
|
|
||||||
# Optionen kombinieren
|
# Optionen kombinieren
|
||||||
ntu --dry-run -v --special /pfad/zu/dateien
|
ntu --dry-run -r -v --special /pfad/zu/dateien
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ _ntu() {
|
||||||
typeset -A opt_args
|
typeset -A opt_args
|
||||||
|
|
||||||
_arguments -C \
|
_arguments -C \
|
||||||
|
'(-r --recursive)'{-r,--recursive}'[Process directories recursively]' \
|
||||||
|
'--conf[Use specific configuration file]:config file:_files' \
|
||||||
'(-n --dry-run --no-changes)'{-n,--dry-run,--no-changes}'[Only preview changes without renaming]' \
|
'(-n --dry-run --no-changes)'{-n,--dry-run,--no-changes}'[Only preview changes without renaming]' \
|
||||||
'(-q --quiet)'{-q,--quiet}'[Suppress output]' \
|
'(-q --quiet)'{-q,--quiet}'[Suppress output]' \
|
||||||
'(-f --force)'{-f,--force}'[Overwrite existing files]' \
|
'(-f --force)'{-f,--force}'[Overwrite existing files]' \
|
||||||
|
|
@ -14,6 +16,7 @@ _ntu() {
|
||||||
'(-v --verbose)'{-v,--verbose}'[Verbose debug output]' \
|
'(-v --verbose)'{-v,--verbose}'[Verbose debug output]' \
|
||||||
'--modify-root[Also rename root directory]' \
|
'--modify-root[Also rename root directory]' \
|
||||||
'--special[Process symlinks and special files]' \
|
'--special[Process symlinks and special files]' \
|
||||||
|
'--no-color[Disable colored output]' \
|
||||||
'(-h --help)'{-h,--help}'[Print help]' \
|
'(-h --help)'{-h,--help}'[Print help]' \
|
||||||
'(-V --version)'{-V,--version}'[Print version]' \
|
'(-V --version)'{-V,--version}'[Print version]' \
|
||||||
'*:path:_files'
|
'*:path:_files'
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ _ntu_completion() {
|
||||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||||
|
|
||||||
# All available options
|
# All available options
|
||||||
opts="--dry-run --no-changes --quiet --force --exclude --verbose --modify-root --special --help --version -n -q -f -e -v -h -V"
|
opts="--recursive --conf --dry-run --no-changes --quiet --force --exclude --verbose --modify-root --special --no-color --help --version -r -n -q -f -e -v -h -V"
|
||||||
|
|
||||||
# Handle options that require arguments
|
# Handle options that require arguments
|
||||||
case "${prev}" in
|
case "${prev}" in
|
||||||
|
|
@ -16,6 +16,11 @@ _ntu_completion() {
|
||||||
COMPREPLY=( $(compgen -W '"*.tmp" "*.log" "*.bak" "*.swp" "*~"' -- ${cur}) )
|
COMPREPLY=( $(compgen -W '"*.tmp" "*.log" "*.bak" "*.swp" "*~"' -- ${cur}) )
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
|
--conf)
|
||||||
|
# Suggest files for config option
|
||||||
|
COMPREPLY=( $(compgen -f -- ${cur}) )
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
complete -c ntu -f -d 'Sanitize file and directory names to Unix conventions'
|
complete -c ntu -f -d 'Sanitize file and directory names to Unix conventions'
|
||||||
|
|
||||||
# Options
|
# Options
|
||||||
|
complete -c ntu -s r -l recursive -d 'Process directories recursively'
|
||||||
|
complete -c ntu -l conf -d 'Use specific configuration file' -r -F
|
||||||
complete -c ntu -s q -l quiet -d 'Suppress output (no rename information)'
|
complete -c ntu -s q -l quiet -d 'Suppress output (no rename information)'
|
||||||
complete -c ntu -s n -l dry-run -d 'Show what would be renamed without making changes'
|
complete -c ntu -s n -l dry-run -d 'Show what would be renamed without making changes'
|
||||||
complete -c ntu -l no-changes -d 'Alias for --dry-run'
|
complete -c ntu -l no-changes -d 'Alias for --dry-run'
|
||||||
|
|
|
||||||
4
index.md
4
index.md
|
|
@ -1,10 +1,10 @@
|
||||||
# Willkommen bei meinem Projekt
|
# Willkommen bei meinem Projekt
|
||||||
NameToUnix - Rust Command line tool for cleaning up directory & file names according to Linux conventions. Recursively replacing offending characters or spaces.
|
NameToUnix - Rust Command line tool for cleaning up directory & file names according to Linux conventions. Replacing offending characters or spaces (recursive with `-r` flag).
|
||||||
|
|
||||||
Dieses Projekt bietet unter Linux eine einfache Lösung für das automatische Umbenennen von Verzeichnissen und Dateien nach dem Entpacken von gezippten Windows-Dateien mit Leerzeichen oder Sonderzeichen im Namen.
|
Dieses Projekt bietet unter Linux eine einfache Lösung für das automatische Umbenennen von Verzeichnissen und Dateien nach dem Entpacken von gezippten Windows-Dateien mit Leerzeichen oder Sonderzeichen im Namen.
|
||||||
|
|
||||||
## Zielsetzung
|
## Zielsetzung
|
||||||
Das Ziel ist es, diese unkonventionellen Dateinamen rekursiv und automatisch sinnvoll umzubenennen.
|
Das Ziel ist es, diese unkonventionellen Dateinamen automatisch sinnvoll umzubenennen. Ab v1.0.0 ist die rekursive Verarbeitung opt-in (`-r` Flag erforderlich).
|
||||||
|
|
||||||
## Inhaltsverzeichnis
|
## Inhaltsverzeichnis
|
||||||
|
|
||||||
|
|
|
||||||
64
install.sh
Executable file
64
install.sh
Executable file
|
|
@ -0,0 +1,64 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Installation script for ntu (NameToUnix)
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "=== NameToUnix Installation ==="
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Check if binary exists
|
||||||
|
if [ ! -f "target/release/ntu" ]; then
|
||||||
|
echo "Error: Binary not found. Please run 'cargo build --release' first."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install binary
|
||||||
|
echo "Installing binary..."
|
||||||
|
sudo cp target/release/ntu /usr/local/bin/
|
||||||
|
sudo chmod 755 /usr/local/bin/ntu
|
||||||
|
echo "✓ Binary installed to /usr/local/bin/ntu"
|
||||||
|
|
||||||
|
# Install man page
|
||||||
|
echo "Installing man page..."
|
||||||
|
sudo cp man/ntu.1 /usr/share/man/man1/
|
||||||
|
sudo chmod 644 /usr/share/man/man1/ntu.1
|
||||||
|
sudo mandb -q
|
||||||
|
echo "✓ Man page installed to /usr/share/man/man1/ntu.1"
|
||||||
|
|
||||||
|
# Install config (user-specific)
|
||||||
|
echo "Installing configuration..."
|
||||||
|
mkdir -p ~/.config/NameToUnix/
|
||||||
|
cp .NameToUnix.conf ~/.config/NameToUnix/config.toml
|
||||||
|
echo "✓ Config installed to ~/.config/NameToUnix/config.toml"
|
||||||
|
|
||||||
|
# Install shell completions
|
||||||
|
echo "Installing shell completions..."
|
||||||
|
|
||||||
|
# Bash
|
||||||
|
if [ -d "/etc/bash_completion.d" ]; then
|
||||||
|
sudo cp completions/ntu.bash /etc/bash_completion.d/ntu
|
||||||
|
echo "✓ Bash completion installed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Zsh
|
||||||
|
if [ -d "/usr/share/zsh/site-functions" ]; then
|
||||||
|
sudo cp completions/_ntu /usr/share/zsh/site-functions/_ntu
|
||||||
|
echo "✓ Zsh completion installed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fish
|
||||||
|
if [ -d "/usr/share/fish/vendor_completions.d" ]; then
|
||||||
|
sudo cp completions/ntu.fish /usr/share/fish/vendor_completions.d/ntu.fish
|
||||||
|
echo "✓ Fish completion installed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== Installation complete ==="
|
||||||
|
echo
|
||||||
|
echo "Test the installation:"
|
||||||
|
echo " ntu --version"
|
||||||
|
echo " man ntu"
|
||||||
|
echo
|
||||||
|
echo "For shell completions to work, restart your shell or run:"
|
||||||
|
echo " source ~/.bashrc (Bash)"
|
||||||
|
echo " source ~/.zshrc (Zsh)"
|
||||||
16
man/ntu.1
16
man/ntu.1
|
|
@ -1,4 +1,4 @@
|
||||||
.TH NTU 1 "2025-02-10" "NameToUnix 0.3.0" "User Commands"
|
.TH NTU 1 "2025-02-10" "NameToUnix 1.0.0" "User Commands"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
ntu \- sanitize file and directory names to Unix conventions
|
ntu \- sanitize file and directory names to Unix conventions
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
|
@ -11,11 +11,19 @@ to make them compatible with Unix/Linux naming conventions. It replaces
|
||||||
spaces with underscores, converts German umlauts to their ASCII equivalents,
|
spaces with underscores, converts German umlauts to their ASCII equivalents,
|
||||||
and removes or replaces problematic special characters.
|
and removes or replaces problematic special characters.
|
||||||
.PP
|
.PP
|
||||||
The tool processes files recursively, starting from the deepest level to
|
By default, the tool processes only the specified paths and their immediate
|
||||||
avoid conflicts with parent directory renames. It preserves file extensions,
|
children. Use the \fB\-r\fR flag to enable recursive processing of subdirectories.
|
||||||
including double extensions like .tar.gz, and handles hidden files correctly.
|
When recursive, it starts from the deepest level to avoid conflicts with parent
|
||||||
|
directory renames. It preserves file extensions, including double extensions
|
||||||
|
like .tar.gz, and handles hidden files correctly.
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
|
.BR \-r ", " \-\-recursive
|
||||||
|
Process directories recursively (default: only immediate children)
|
||||||
|
.TP
|
||||||
|
.BR \-\-conf " \fIFILE\fR"
|
||||||
|
Use a specific configuration file instead of the default hierarchy
|
||||||
|
.TP
|
||||||
.BR \-q ", " \-\-quiet
|
.BR \-q ", " \-\-quiet
|
||||||
Suppress output (no rename information on stdout)
|
Suppress output (no rename information on stdout)
|
||||||
.TP
|
.TP
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,14 @@ pub struct Cli {
|
||||||
/// Pfade (Dateien und Verzeichnisse) zum rekursiven Anpassen
|
/// Pfade (Dateien und Verzeichnisse) zum rekursiven Anpassen
|
||||||
pub paths: Vec<PathBuf>,
|
pub paths: Vec<PathBuf>,
|
||||||
|
|
||||||
|
/// Explizite Konfigurationsdatei (bypassed Standard-Hierarchie)
|
||||||
|
#[clap(long = "conf", value_name = "FILE")]
|
||||||
|
pub config_file: Option<PathBuf>,
|
||||||
|
|
||||||
|
/// Rekursive Verarbeitung von Unterverzeichnissen aktivieren
|
||||||
|
#[clap(short = 'r', long)]
|
||||||
|
pub recursive: bool,
|
||||||
|
|
||||||
/// Ausgaben unterdrücken (keine Umbenennungsinfos auf stdout)
|
/// Ausgaben unterdrücken (keine Umbenennungsinfos auf stdout)
|
||||||
#[clap(short, long)]
|
#[clap(short, long)]
|
||||||
pub quiet: bool,
|
pub quiet: bool,
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,19 @@ impl Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Lädt Konfiguration aus spezifischer Datei (fehlschlägt bei nicht-existierender Datei)
|
||||||
|
pub fn from_file(path: &Path, verbose: bool) -> Result<Self> {
|
||||||
|
if !path.exists() {
|
||||||
|
return Err(anyhow::anyhow!(
|
||||||
|
"Konfigurationsdatei nicht gefunden: {}",
|
||||||
|
path.display()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Self::load_internal(path, verbose)
|
||||||
|
}
|
||||||
|
|
||||||
/// Sucht nach Konfigurationsdateien in verschiedenen Orten und kombiniert sie
|
/// Sucht nach Konfigurationsdateien in verschiedenen Orten und kombiniert sie
|
||||||
pub fn from_default_locations(verbose: bool) -> Result<Self> {
|
pub fn from_default_locations(verbose: bool) -> Result<Self> {
|
||||||
// Prioritätenreihenfolge (später überschreibt früher):
|
// Prioritätenreihenfolge (später überschreibt früher):
|
||||||
|
|
|
||||||
21
src/main.rs
21
src/main.rs
|
|
@ -60,9 +60,13 @@ fn main() -> Result<()> {
|
||||||
colored::control::set_override(false);
|
colored::control::set_override(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optional Konfigurationsdatei laden
|
// Config-Datei laden: entweder --conf oder Standard-Hierarchie
|
||||||
let config = Config::from_default_locations(args.verbose)?;
|
let config = if let Some(config_path) = &args.config_file {
|
||||||
// let config = Config::load(".NameToUnix.conf", args.verbose)?;
|
Config::from_file(config_path, args.verbose)
|
||||||
|
.with_context(|| format!("Fehler beim Laden der Konfiguration: {}", config_path.display()))?
|
||||||
|
} else {
|
||||||
|
Config::from_default_locations(args.verbose)?
|
||||||
|
};
|
||||||
|
|
||||||
// Ausschlussmuster (Glob-Patterns) vorbereiten - Default-Excludes + User-Excludes
|
// Ausschlussmuster (Glob-Patterns) vorbereiten - Default-Excludes + User-Excludes
|
||||||
let mut all_excludes = DEFAULT_EXCLUDES
|
let mut all_excludes = DEFAULT_EXCLUDES
|
||||||
|
|
@ -90,7 +94,16 @@ fn main() -> Result<()> {
|
||||||
for path in &args.paths {
|
for path in &args.paths {
|
||||||
// Alle Einträge sammeln, damit zuerst die tiefsten umbenannt werden
|
// Alle Einträge sammeln, damit zuerst die tiefsten umbenannt werden
|
||||||
let mut entries = Vec::new();
|
let mut entries = Vec::new();
|
||||||
for entry_result in WalkDir::new(path)
|
|
||||||
|
let walker = if args.recursive {
|
||||||
|
// Recursive: unbegrenzte Tiefe
|
||||||
|
WalkDir::new(path)
|
||||||
|
} else {
|
||||||
|
// Non-recursive: max_depth(1) verarbeitet nur direkte Kinder
|
||||||
|
WalkDir::new(path).max_depth(1)
|
||||||
|
};
|
||||||
|
|
||||||
|
for entry_result in walker
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_entry(|e| !is_excluded(e, &exclude_patterns))
|
.filter_entry(|e| !is_excluded(e, &exclude_patterns))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
{"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":{}}
|
{"rustc_fingerprint":4740973386762217857,"outputs":{"17747080675513052775":{"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":""},"7971740275564407648":{"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":{}}
|
||||||
|
|
@ -30,7 +30,7 @@ fn test_dry_run_no_changes() {
|
||||||
fs::write(&file_path, "test content").unwrap();
|
fs::write(&file_path, "test content").unwrap();
|
||||||
|
|
||||||
let mut cmd = Command::new(cargo_bin!("ntu"));
|
let mut cmd = Command::new(cargo_bin!("ntu"));
|
||||||
cmd.arg("--dry-run").arg(temp_dir.path());
|
cmd.arg("--dry-run").arg("-r").arg(temp_dir.path());
|
||||||
cmd.assert().success();
|
cmd.assert().success();
|
||||||
|
|
||||||
// File should still have spaces (not renamed)
|
// File should still have spaces (not renamed)
|
||||||
|
|
@ -45,7 +45,7 @@ fn test_actual_rename() {
|
||||||
fs::write(&file_path, "test content").unwrap();
|
fs::write(&file_path, "test content").unwrap();
|
||||||
|
|
||||||
let mut cmd = Command::new(cargo_bin!("ntu"));
|
let mut cmd = Command::new(cargo_bin!("ntu"));
|
||||||
cmd.arg(temp_dir.path());
|
cmd.arg("-r").arg(temp_dir.path());
|
||||||
cmd.assert().success();
|
cmd.assert().success();
|
||||||
|
|
||||||
// File should be renamed
|
// File should be renamed
|
||||||
|
|
@ -60,7 +60,7 @@ fn test_hidden_files_preserved() {
|
||||||
fs::write(&file_path, "*.tmp").unwrap();
|
fs::write(&file_path, "*.tmp").unwrap();
|
||||||
|
|
||||||
let mut cmd = Command::new(cargo_bin!("ntu"));
|
let mut cmd = Command::new(cargo_bin!("ntu"));
|
||||||
cmd.arg(temp_dir.path());
|
cmd.arg("-r").arg(temp_dir.path());
|
||||||
cmd.assert().success();
|
cmd.assert().success();
|
||||||
|
|
||||||
// Hidden file should not be renamed
|
// Hidden file should not be renamed
|
||||||
|
|
@ -74,7 +74,7 @@ fn test_hidden_file_with_spaces() {
|
||||||
fs::write(&file_path, "config content").unwrap();
|
fs::write(&file_path, "config content").unwrap();
|
||||||
|
|
||||||
let mut cmd = Command::new(cargo_bin!("ntu"));
|
let mut cmd = Command::new(cargo_bin!("ntu"));
|
||||||
cmd.arg(temp_dir.path());
|
cmd.arg("-r").arg(temp_dir.path());
|
||||||
cmd.assert().success();
|
cmd.assert().success();
|
||||||
|
|
||||||
// Hidden file should be renamed but keep leading dot
|
// Hidden file should be renamed but keep leading dot
|
||||||
|
|
@ -89,7 +89,7 @@ fn test_umlaut_conversion() {
|
||||||
fs::write(&file_path, "test").unwrap();
|
fs::write(&file_path, "test").unwrap();
|
||||||
|
|
||||||
let mut cmd = Command::new(cargo_bin!("ntu"));
|
let mut cmd = Command::new(cargo_bin!("ntu"));
|
||||||
cmd.arg(temp_dir.path());
|
cmd.arg("-r").arg(temp_dir.path());
|
||||||
cmd.assert().success();
|
cmd.assert().success();
|
||||||
|
|
||||||
// Umlaut should be converted
|
// Umlaut should be converted
|
||||||
|
|
@ -104,7 +104,7 @@ fn test_double_extension() {
|
||||||
fs::write(&file_path, "archive").unwrap();
|
fs::write(&file_path, "archive").unwrap();
|
||||||
|
|
||||||
let mut cmd = Command::new(cargo_bin!("ntu"));
|
let mut cmd = Command::new(cargo_bin!("ntu"));
|
||||||
cmd.arg(temp_dir.path());
|
cmd.arg("-r").arg(temp_dir.path());
|
||||||
cmd.assert().success();
|
cmd.assert().success();
|
||||||
|
|
||||||
// Should keep .tar.gz intact
|
// Should keep .tar.gz intact
|
||||||
|
|
@ -123,6 +123,7 @@ fn test_exclude_pattern() {
|
||||||
let mut cmd = Command::new(cargo_bin!("ntu"));
|
let mut cmd = Command::new(cargo_bin!("ntu"));
|
||||||
cmd.arg("--exclude")
|
cmd.arg("--exclude")
|
||||||
.arg("*.tmp")
|
.arg("*.tmp")
|
||||||
|
.arg("-r")
|
||||||
.arg(temp_dir.path());
|
.arg(temp_dir.path());
|
||||||
cmd.assert().success();
|
cmd.assert().success();
|
||||||
|
|
||||||
|
|
@ -139,7 +140,7 @@ fn test_quiet_mode() {
|
||||||
fs::write(&file_path, "test").unwrap();
|
fs::write(&file_path, "test").unwrap();
|
||||||
|
|
||||||
let mut cmd = Command::new(cargo_bin!("ntu"));
|
let mut cmd = Command::new(cargo_bin!("ntu"));
|
||||||
cmd.arg("--quiet").arg(temp_dir.path());
|
cmd.arg("--quiet").arg("-r").arg(temp_dir.path());
|
||||||
cmd.assert()
|
cmd.assert()
|
||||||
.success()
|
.success()
|
||||||
.stdout(predicate::str::is_empty());
|
.stdout(predicate::str::is_empty());
|
||||||
|
|
@ -155,7 +156,7 @@ fn test_multiple_paths() {
|
||||||
fs::write(&file2, "test2").unwrap();
|
fs::write(&file2, "test2").unwrap();
|
||||||
|
|
||||||
let mut cmd = Command::new(cargo_bin!("ntu"));
|
let mut cmd = Command::new(cargo_bin!("ntu"));
|
||||||
cmd.arg(temp_dir1.path()).arg(temp_dir2.path());
|
cmd.arg("-r").arg(temp_dir1.path()).arg(temp_dir2.path());
|
||||||
cmd.assert().success();
|
cmd.assert().success();
|
||||||
|
|
||||||
// Both files should be renamed
|
// Both files should be renamed
|
||||||
|
|
@ -170,7 +171,7 @@ fn test_parentheses_removed() {
|
||||||
fs::write(&file_path, "test").unwrap();
|
fs::write(&file_path, "test").unwrap();
|
||||||
|
|
||||||
let mut cmd = Command::new(cargo_bin!("ntu"));
|
let mut cmd = Command::new(cargo_bin!("ntu"));
|
||||||
cmd.arg(temp_dir.path());
|
cmd.arg("-r").arg(temp_dir.path());
|
||||||
cmd.assert().success();
|
cmd.assert().success();
|
||||||
|
|
||||||
// Parentheses should be replaced with underscores
|
// Parentheses should be replaced with underscores
|
||||||
|
|
@ -185,10 +186,74 @@ fn test_special_identifiers_preserved() {
|
||||||
fs::write(&file_path, "test").unwrap();
|
fs::write(&file_path, "test").unwrap();
|
||||||
|
|
||||||
let mut cmd = Command::new(cargo_bin!("ntu"));
|
let mut cmd = Command::new(cargo_bin!("ntu"));
|
||||||
cmd.arg(temp_dir.path());
|
cmd.arg("-r").arg(temp_dir.path());
|
||||||
cmd.assert().success();
|
cmd.assert().success();
|
||||||
|
|
||||||
// C++ should be preserved
|
// C++ should be preserved
|
||||||
assert!(!file_path.exists());
|
assert!(!file_path.exists());
|
||||||
assert!(temp_dir.path().join("C++_Guide.pdf").exists());
|
assert!(temp_dir.path().join("C++_Guide.pdf").exists());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_non_recursive_default() {
|
||||||
|
let temp_dir = TempDir::new().unwrap();
|
||||||
|
fs::create_dir(temp_dir.path().join("subdir")).unwrap();
|
||||||
|
let file1 = temp_dir.path().join("top file.txt");
|
||||||
|
let file2 = temp_dir.path().join("subdir").join("nested file.txt");
|
||||||
|
fs::write(&file1, "test1").unwrap();
|
||||||
|
fs::write(&file2, "test2").unwrap();
|
||||||
|
|
||||||
|
let mut cmd = Command::new(cargo_bin!("ntu"));
|
||||||
|
cmd.arg(temp_dir.path());
|
||||||
|
cmd.assert().success();
|
||||||
|
|
||||||
|
// Top-Level umbenannt
|
||||||
|
assert!(temp_dir.path().join("top_file.txt").exists());
|
||||||
|
// Nested NICHT umbenannt (non-recursive)
|
||||||
|
assert!(file2.exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_recursive_flag() {
|
||||||
|
let temp_dir = TempDir::new().unwrap();
|
||||||
|
fs::create_dir(temp_dir.path().join("subdir")).unwrap();
|
||||||
|
let file1 = temp_dir.path().join("top file.txt");
|
||||||
|
let file2 = temp_dir.path().join("subdir").join("nested file.txt");
|
||||||
|
fs::write(&file1, "test1").unwrap();
|
||||||
|
fs::write(&file2, "test2").unwrap();
|
||||||
|
|
||||||
|
let mut cmd = Command::new(cargo_bin!("ntu"));
|
||||||
|
cmd.arg("-r").arg(temp_dir.path());
|
||||||
|
cmd.assert().success();
|
||||||
|
|
||||||
|
// Beide umbenannt
|
||||||
|
assert!(temp_dir.path().join("top_file.txt").exists());
|
||||||
|
assert!(temp_dir.path().join("subdir").join("nested_file.txt").exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_conf_option_valid_file() {
|
||||||
|
let temp_dir = TempDir::new().unwrap();
|
||||||
|
let config_file = temp_dir.path().join("custom.toml");
|
||||||
|
fs::write(&config_file, "[replacements]\n\"test\" = \"xyz\"").unwrap();
|
||||||
|
let file_path = temp_dir.path().join("test_file.txt");
|
||||||
|
fs::write(&file_path, "content").unwrap();
|
||||||
|
|
||||||
|
let mut cmd = Command::new(cargo_bin!("ntu"));
|
||||||
|
cmd.arg("--conf").arg(&config_file).arg(temp_dir.path());
|
||||||
|
cmd.assert().success();
|
||||||
|
|
||||||
|
assert!(temp_dir.path().join("xyz_file.txt").exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_conf_option_missing_file() {
|
||||||
|
let temp_dir = TempDir::new().unwrap();
|
||||||
|
let nonexistent = temp_dir.path().join("nonexistent.toml");
|
||||||
|
|
||||||
|
let mut cmd = Command::new(cargo_bin!("ntu"));
|
||||||
|
cmd.arg("--conf").arg(&nonexistent).arg(temp_dir.path());
|
||||||
|
cmd.assert()
|
||||||
|
.failure()
|
||||||
|
.stderr(predicate::str::contains("nicht gefunden"));
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue