Add rename_safe.sh
This commit is contained in:
parent
8b45bb1315
commit
a5422c2b3f
1 changed files with 97 additions and 0 deletions
97
rename_safe.sh
Normal file
97
rename_safe.sh
Normal file
|
@ -0,0 +1,97 @@
|
|||
#!/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
|
Loading…
Add table
Add a link
Reference in a new issue