Thank you very much for your support — this was the key to solving our problem!
At first, I thought the folder creation wasn’t case-sensitive, assuming it was random and that once a folder was created everything went there.
I tested more than 20 attachments, only to find that some were corrupt and some were missing, not realizing there were actually two different issues.
I wrote a small script thanks to your feedback to reorganize the folders. I’m happy to share it — you only need to set your upload folder path and run it.
It includes a DRYRUN option so you can test and review the log safely before moving files for real (set DRYRUN=0 to apply the changes).
#!/usr/bin/env bash
set -euo pipefail
# === SETTINGS ===
BASE="upload_path" # ← your actual upload path
DRYRUN=1 # 1 = simulate (no move), 0 = move for real
LOG="/var/log/osticket_attachments_reorg.log"
# Site user/group in ISPConfig (adjust if different)
WEBUSER="webuser"
WEBGROUP="clientnumber"
umask 027
touch "$LOG" && chown "$WEBUSER":"$WEBGROUP" "$LOG" || true
echo "=== $(date '+%F %T') Start reorganization in $BASE (DRYRUN=$DRYRUN) ===" | tee -a "$LOG"
# Traverse files in BASE/<folder>/<file>
find "$BASE" -maxdepth 2 -type f -printf '%h/%f\n' | while IFS= read -r path; do
dir=$(dirname "$path")
file=$(basename "$path")
[[ -z "$file" ]] && continue
first="${file:0:1}" # first character of the key
dest_dir="$BASE/$first" # correct (case-sensitive) folder
if [[ "$dir" != "$dest_dir" ]]; then
# Create destination folder if it doesn’t exist and fix ownership
if [[ ! -d "$dest_dir" ]]; then
mkdir -p "$dest_dir"
chown "$WEBUSER":"$WEBGROUP" "$dest_dir" || true
chmod 0750 "$dest_dir" || true
fi
if [[ "$DRYRUN" -eq 1 ]]; then
echo "[DRYRUN] mv '$path' '$dest_dir/'" | tee -a "$LOG"
else
# Move without overwriting existing files (rare cases)
if [[ -e "$dest_dir/$file" ]]; then
echo "[SKIP] already exists '$dest_dir/$file' — check conflict" | tee -a "$LOG"
else
echo "[MOVE] '$path' -> '$dest_dir/$file'" | tee -a "$LOG"
mv "$path" "$dest_dir/$file"
chown "$WEBUSER":"$WEBGROUP" "$dest_dir/$file" || true
chmod 0640 "$dest_dir/$file" || true
fi
fi
fi
done
echo "=== $(date '+%F %T') End reorganization (DRYRUN=$DRYRUN) ===" | tee -a "$LOG"
After fixing this, we could finally see some files (like .txt), but others still didn’t open correctly — even though they existed. When we started comparing checksums, we noticed that every file was slightly different.
I even allowed direct access to the upload folder and tested one of the files I had uploaded from my computer; it didn’t work once accessed without an extension, but it did work if I uploaded it with an extension.
That’s when we discovered that FileZilla was using Auto transfer mode instead of Binary, so it was re-encoding (compressing) the files during transfer.
Once we deleted everything, re-uploaded all attachments in Binary mode, and ran the script again, everything started working perfectly.
Everything was possible thanks to your help — thank you again! 🙌