97 lines
No EOL
2.3 KiB
Bash
97 lines
No EOL
2.3 KiB
Bash
#!/bin/bash
|
|
|
|
# Handle --dry-run flag
|
|
DRY_RUN=0
|
|
if [ "$1" = "--dry-run" ]; then
|
|
DRY_RUN=1
|
|
shift
|
|
fi
|
|
|
|
# Directory to process (default: current directory)
|
|
DIR="."
|
|
if [ -n "$1" ]; then
|
|
DIR="$1"
|
|
fi
|
|
|
|
# Function to process and rename a file
|
|
process_file() {
|
|
local original="$1"
|
|
local base ext modified sanitized_base
|
|
|
|
# Skip directories and non-regular files
|
|
[ -f "$original" ] || return 0
|
|
|
|
# Split base and extension
|
|
if [[ "$original" == *.* ]]; then
|
|
ext=".${original##*.}"
|
|
base="${original%.*}"
|
|
else
|
|
base="$original"
|
|
ext=""
|
|
fi
|
|
|
|
# Sanitize base only, not the extension
|
|
sanitized_base=$(echo "$base" | tr ' ' '_' | tr '[:upper:]' '[:lower:]')
|
|
sanitized_base=$(echo "$sanitized_base" | sed 's/[^a-zA-Z0-9._-]//g')
|
|
|
|
# Truncate base to 250 chars to avoid hitting filesystem limits
|
|
base_truncated="${sanitized_base:0:250}"
|
|
|
|
# Rebuild filename with sanitized base and original extension
|
|
modified="$base_truncated$ext"
|
|
|
|
# Collapse multiple underscores
|
|
modified=$(echo "$modified" | tr -s '_')
|
|
|
|
# Trim leading/trailing underscores
|
|
modified=$(echo "$modified" | sed 's/^_//' | sed 's/_$//')
|
|
|
|
# Skip if empty
|
|
if [ -z "$modified" ]; then
|
|
echo "Error: Empty filename after sanitizing '$original'" >&2
|
|
return 1
|
|
fi
|
|
|
|
# Skip if no change
|
|
if [ "$original" = "$modified" ]; then
|
|
echo "No changes needed: '$original'"
|
|
return 0
|
|
fi
|
|
|
|
# Collision handling
|
|
counter=1
|
|
original_modified="$modified"
|
|
while [ -e "$modified" ]; do
|
|
modified="${base_truncated}_${counter}${ext}"
|
|
# Truncate again to avoid going over 255 chars
|
|
modified="${modified:0:255}"
|
|
((counter++))
|
|
done
|
|
|
|
# Dry run
|
|
if [ "$DRY_RUN" -eq 1 ]; then
|
|
echo "Dry-run: Would rename '$original' → '$modified'"
|
|
return 0
|
|
fi
|
|
|
|
# Rename file
|
|
if mv -- "$original" "$modified"; then
|
|
echo "Renamed: '$original' → '$modified'"
|
|
else
|
|
echo "Error: Failed to rename '$original'" >&2
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Enter target directory
|
|
cd "$DIR" || { echo "Error: Failed to change directory to '$DIR'" >&2; exit 1; }
|
|
|
|
# Process all non-hidden files
|
|
for file in *; do
|
|
process_file "$file"
|
|
done
|
|
|
|
# Optional: process hidden files (uncomment below)
|
|
# for file in .??*; do
|
|
# process_file "$file"
|
|
# done |