Skip to main content

Auto Rename Uploads with Timestamp

This page documents an automation pattern for Docusaurus sites: watch a static image folder and rename newly-uploaded files with a timestamp to prevent filename collisions.

Quick Summary
  • Watch a directory (example: opt/docker-data/apps/docusaurus/site/static/img) with inotifywait.
  • On create/move events, rename files to original_name-YYYYMMDDHHMM.ext (plus a numeric suffix on collisions).
  • Run it as a systemd --user service so it survives terminal sessions.
warning

Renaming files is destructive for existing links. If you already referenced an image name in Markdown/MDX, renaming the file will break the link until you update the docs.

When this is useful

  • You upload screenshots via SFTP or a file manager and want guaranteed unique names.
  • You want a predictable naming scheme for later cleanup/search.
  • You want to avoid manual "rename before upload" habits.

How it works

The workflow is:

The watcher should ignore:

  • dotfiles (example: .DS_Store)
  • partial uploads (example: .part, .crdownload)
  • non-image extensions

Paths and unit names

Adjust these to your server layout:

  • Watched directory: /opt/docker-data/apps/docusaurus/site/static/img
  • Script location (example): /home/rezriz/github/scripts/watch_rename_uploads.sh
  • Service name: watch-rename-uploads.service
  • User unit path: ~/.config/systemd/user/watch-rename-uploads.service

Install dependencies

Install inotify-tools:

install-inotify-tools-apt.sh
sudo apt update
sudo apt install -y inotify-tools

Watcher script

Keep the script in a stable location and make it executable.

Example watcher script
watch_rename_uploads.sh
#!/usr/bin/env bash
set -euo pipefail

WATCH_DIR="/opt/docker-data/apps/docusaurus/site/static/img"
SETTLE_SECONDS="1"

# Only rename these extensions.
ALLOW_RE='\.(jpe?g|png|webp|gif|svg|avif)$'

inotifywait -m -e close_write -e moved_to --format '%w%f' "$WATCH_DIR" | while read -r path; do
name="$(basename "$path")"

# Ignore dotfiles and common temp extensions.
[[ "$name" == .* ]] && continue
[[ "$name" == *.tmp || "$name" == *.part || "$name" == *.crdownload ]] && continue

# Only rename allowed extensions.
[[ "$name" =~ $ALLOW_RE ]] || continue

sleep "$SETTLE_SECONDS"

base="${name%.*}"
ext="${name##*.}"
stamp="$(date +%Y%m%d%H%M)"

candidate="$WATCH_DIR/${base}-${stamp}.${ext}"
if [[ ! -e "$candidate" ]]; then
mv -n -- "$path" "$candidate"
continue
fi

for i in $(seq -w 1 99); do
candidate="$WATCH_DIR/${base}-${stamp}-${i}.${ext}"
if [[ ! -e "$candidate" ]]; then
mv -n -- "$path" "$candidate"
break
fi
done
done

systemd user service

Create a systemd --user unit that runs the script.

Example systemd user unit
~/.config/systemd/user/watch-rename-uploads.service
[Unit]
Description=Watch Docusaurus static img folder and auto-rename uploads
After=default.target

[Service]
Type=simple
ExecStart=/home/rezriz/github/scripts/watch_rename_uploads.sh
Restart=always
RestartSec=2

[Install]
WantedBy=default.target

Enable and start it:

enable-and-start-user-service.sh
systemctl --user daemon-reload
systemctl --user enable --now watch-rename-uploads.service

Enable user lingering

If you want the service to run when you are logged out, enable lingering for the user:

enable-user-lingering.sh
sudo loginctl enable-linger rezriz
warning

loginctl enable-linger allows the user's systemd --user instance to run without an active login session. Use it only for accounts you trust and keep that account secured (SSH keys, strong password policy, MFA where possible).

Manage the service

Check status:

check-service-status.sh
systemctl --user status watch-rename-uploads.service --no-pager --full

View logs:

follow-service-logs.sh
journalctl --user -u watch-rename-uploads.service -f

Restart after changes:

restart-service.sh
systemctl --user restart watch-rename-uploads.service

Stop the service:

stop-service.sh
systemctl --user stop watch-rename-uploads.service

Troubleshooting

Nothing is being renamed

  • Confirm the service is running.
  • Confirm WATCH_DIR matches the real upload directory.
  • Run the script manually to see errors (permissions, missing inotifywait).

Files rename before upload completes

Increase the settle delay (SETTLE_SECONDS) or adjust the inotifywait event list to fit your upload method.

You renamed a file that is already referenced

Search for the old filename in docs and update references, or rename the file back.