#!/bin/bash
export PATH=/usr/bin:/bin:/usr/sbin:/sbin
########################################################################################################
#
# Jamf Self Service Script to check user's OneDrive folder for illegal
# characters, leading or trailing spaces and corrects them to
# allow smooth synchronization.
#
########################################################################################################
# Global variables
COMPANY="X"
JAMFBIN="/usr/local/jamf/bin/jamf"
NOTIFY="/Applications/Utilities/Notifier.app/Contents/MacOS/Notifier"
ONEDRIVE="/Applications/OneDrive.app"
LOG="/private/var/log/OneDriveFixLog.log"
USER=$( /usr/sbin/scutil <<< "show State:/Users/ConsoleUser" | /usr/bin/awk -F': ' '/[[:space:]]+Name[[:space:]]:/ { if ( $2 != "loginwindow" ) { print $2 }}' )
ONEDRIVE_FOLDER="/Users/$USER/Library/CloudStorage/OneDrive-$COMPANY"
# Logging function
# $1 = msg
logd() {
echo "[$(date +'%m.%d.%Y %I:%M:%S')]: $1" >> "$LOG"
}
# Cleanup function, removes temp files and restarts OneDrive
finish() {
[[ -z "$fixchars" ]] || rm -f "$fixchars" 2>> "$LOG"
[[ -z "$fixtrail" ]] || rm -f "$fixtrail" 2>> "$LOG"
[[ -z "$fixlead" ]] || rm -f "$fixlead" 2>> "$LOG"
[[ $(pgrep -x "OneDrive") ]] || open -gj "$ONEDRIVE" 2>> "$LOG"
# Headache
logd "<\3 Coffee"
kill "$caffeinatepid" 2>> "$LOG"
logd "Clean up complete."
}
# Removed due to errors
# trap finish HUP INT QUIT TERM
# Filename correction functions
fix_trailing_chars() {
local linecount counter line name path fixedname
linecount="$(wc -l "$fixtrail" | awk '{print $1}')"
counter="$linecount"
while ! [ "$counter" -eq 0 ]; do
line="$(sed -n "${counter}"p "$fixtrail")"
name="$(basename "$line")"
path="$(dirname "$line")"
fixedname="$(echo "$name" | tr '.' '-' | awk '{sub(/[ \t]+$/, "")};1')"
if [[ -f "$path"'/'"$fixedname" ]] || [[ -d "$path"'/'"$fixedname" ]]; then
mv -vf "$line" "$path"'/'"$fixedname"'-'"$(jot -nr 1 100000 999999)" 2>> "$LOG"
else
mv -vf "$line" "$path"'/'"$fixedname" 2>> "$LOG"
fi
((counter = counter - 1))
done
}
fix_leading_spaces() {
local linecount counter line name path fixedname
linecount="$(wc -l "$fixlead" | awk '{print $1}')"
counter="$linecount"
while ! [ "$counter" -eq 0 ]; do
line="$(sed -n "${counter}"p "$fixlead")"
name="$(basename "$line")"
path="$(dirname "$line")"
fixedname="$(echo "$name" | sed -e 's/^[ \t]*//')"
if [[ -f "$path"'/'"$fixedname" ]] || [[ -d "$path"'/'"$fixedname" ]]; then
mv -vf "$line" "$path"'/'"$fixedname"'-'"$(jot -nr 1 100000 999999)" 2>> "$LOG"
else
mv -vf "$line" "$path"'/'"$fixedname" 2>> "$LOG"
fi
((counter = counter - 1))
done
}
fix_names() {
local linecount counter line name path fixedname
linecount="$(wc -l "$fixchars" | awk '{print $1}')"
counter="$linecount"
while ! [ "$counter" -eq 0 ]; do
line="$(sed -n "${counter}"p "$fixchars")"
name="$(basename "$line")"
path="$(dirname "$line")"
fixedname="$(echo "$name" | tr ':' '-' | tr '\\' '-' | tr '?' '-' | tr '*' '-' | tr '"' '-' | tr '<' '-' | tr '>' '-' | tr '|' '-')"
if [[ -f "$path"'/'"$fixedname" ]] || [[ -d "$path"'/'"$fixedname" ]]; then
mv -vf "$line" "$path"'/'"$fixedname"'-'"$(jot -nr 1 100000 999999)" 2>> "$LOG"
else
mv -vf "$line" "$path"'/'"$fixedname" 2>> "$LOG"
fi
((counter = counter - 1))
done
}
main() {
old_log_dir="/var/log/onedrive-fixlogs"
# Init log, remove old log
if [[ ! -f "$LOG" ]]; then
touch "$LOG"
logd "Log Init"
if [[ -d "$old_log_dir" ]]; then
rm -drf "$old_log_dir" 2>> "$LOG"
fi
else
echo "" >> "$LOG"
fi
# START
logd "STARTING RUN"
# Caffeinate
logd "<3 Coffee"
/usr/bin/caffeinate -d -i -m -u &
caffeinatepid=$!
logd "User: $USER"
logd "OneDrive Folder Path: $ONEDRIVE_FOLDER"
set -o pipefail
unset fixchars fixtrail fixlead
$NOTIFY --type alert --messagebutton "Close" --title "OneDrive Name Fix" --message "Running checks..." 2>> "$LOG"
# # Get the user
# local -r loggedinuser=$( /usr/sbin/scutil <<< "show State:/Users/ConsoleUser" | /usr/bin/awk -F': ' '/[[:space:]]+Name[[:space:]]:/ { if ( $2 != "loginwindow" ) { print $2 }}' )
#
# # Set OneDrive folder name (specify onedrive folder name here)
# local -r onedrivefolder="/Users/$loggedinuser/OneDrive - $COMPANY"
# Get date
local -r fixdate=$(date +'%Y.%m.%d-%H.%M')
# Check if file system is APFS
local apfscheck
apfscheck="$(diskutil info / | awk '/Type \(Bundle\)/ {print $3}')"
if [[ "$apfscheck" == "apfs" ]]; then
logd "File system is APFS, the script may continue."
else
logd "File system not supported, aborting."
$JAMFBIN displayMessage -message "The file system on this Mac is not supported, please contact IT." 2>> "$LOG"
exit 1
fi
# Check if OneDrive folder is present
# Make backup using APFS clonefile, prevent the backup from being indexed by Spotlight
if [ -d "$ONEDRIVE_FOLDER" ]; then
$NOTIFY --type alert --messagebutton "Close" --title "OneDrive Name Fix" --message "Making a backup..." 2>> "$LOG"
logd "OneDrive directory is present. Stopping OneDrive."
killall "OneDrive" || true 2>> "$LOG"
beforefix_size=$(du -sk "$ONEDRIVE_FOLDER" | awk -F '\t' '{print $1}')
readonly beforefix_size
beforefix_filecount=$(find "$ONEDRIVE_FOLDER" | wc -l | sed -e 's/^ *//')
readonly beforefix_filecount
logd "The OneDrive folder is using $beforefix_size KB and the file count is $beforefix_filecount before fixing filenames."
rm -drf "/Users/$USER/OD-Backup-"*"-"* 2>> "$LOG"
mkdir -p "/Users/$USER/OD-Backup-$fixdate/$fixdate.noindex" 2>> "$LOG"
chown "$USER":staff "/Users/$USER/OD-Backup-$fixdate" 2>> "$LOG"
chown "$USER":staff "/Users/$USER/OD-Backup-$fixdate/$fixdate.noindex" 2>> "$LOG"
touch "/Users/$USER/OD-Backup-$fixdate/$fixdate.noindex/.metadata_never_index" 2>> "$LOG"
cp -cpR "$ONEDRIVE_FOLDER" "/Users/$USER/OD-Backup-$fixdate/$fixdate.noindex" 2>> "$LOG"
logd "APFS clonefile backup created at /Users/$USER/OD-Backup-$fixdate/$fixdate.noindex."
else
logd "OneDrive directory not present, aborting."
$JAMFBIN displayMessage -message "Cannot find the OneDrive folder. Ask IT to help set up OneDrive, or change the name of the folder" 2>> "$LOG"
exit 1
fi
$NOTIFY --type alert --messagebutton "Close" --title "OneDrive Name Fix" --message "Hang tight. Running fixes..." 2>> "$LOG"
# Fix directory filenames
logd "Fixing illegal characters in directory names"
fixchars="$(mktemp)"
readonly fixchars
find "${ONEDRIVE_FOLDER}" -type d -name '*[\\:*?"<>|]*' -print > "$fixchars" 2>> "$LOG"
fix_names
logd "Fixing trailing characters in directory names"
fixtrail="$(mktemp)"
readonly fixtrail
find "${ONEDRIVE_FOLDER}" -type d -name "* " -print > "$fixtrail" 2>> "$LOG"
find "${ONEDRIVE_FOLDER}" -type d -name "*." -print >> "$fixtrail" 2>> "$LOG"
fix_trailing_chars
logd "Fixing leading spaces in directory names"
fixlead="$(mktemp)"
readonly fixlead
find "${ONEDRIVE_FOLDER}" -type d -name " *" -print > "$fixlead" 2>> "$LOG"
fix_leading_spaces
# Fix all other filenames
logd "Fixing illegal characters in filenames"
find "${ONEDRIVE_FOLDER}" -name '*[\\:*?"<>|]*' -print > "$fixchars" 2>> "$LOG"
fix_names
logd "Fixing trailing characters in filenames"
find "${ONEDRIVE_FOLDER}" -name "* " -print > "$fixtrail" 2>> "$LOG"
find "${ONEDRIVE_FOLDER}" -name "*." -print >> "$fixtrail" 2>> "$LOG"
fix_trailing_chars
logd "Fixing leading spaces in filenames"
find "${ONEDRIVE_FOLDER}" -name " *" -print > "$fixlead" 2>> "$LOG"
fix_leading_spaces
# Check OneDrive directory size and filecount after applying name fixes
afterfix_size=$(du -sk "$ONEDRIVE_FOLDER" | awk -F '\t' '{print $1}')
readonly afterfix_size
afterfix_filecount=$(find "$ONEDRIVE_FOLDER" | wc -l | sed -e 's/^ *//')
readonly afterfix_filecount
logd "The OneDrive folder is using $afterfix_size KB and the file count is $afterfix_filecount after fixing filenames. Restarting OneDrive."
if [[ "$beforefix_filecount" -eq "$afterfix_filecount" ]]; then
rm -drf "/Users/$USER/OD-Backup-"*"-"* 2>> "$LOG"
$JAMFBIN displayMessage -message "File names have been successfully corrected. The backup has been removed." 2>> "$LOG"
else
$JAMFBIN displayMessage -message "Something went wrong. A backup has been placed in OD-Backup-$fixdate in your user folder. Ask IT to help restore the backup." 2>> "$LOG"
fi
}
# Call main
main
# Cleanup
finish
exit 0 #Success
exit 1 #Failure