Last active
September 2, 2024 21:46
-
-
Save inoperable/6041a6cc9426043bb830f4f4ed658449 to your computer and use it in GitHub Desktop.
export defaults for all domains in macOS into separate .plist files for editing and importing, files are written into $HOME/defaults
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env zsh | |
function exportDefaults { | |
local outdir="$HOME/defaults" | |
local outdirApple="$outdir/apple" | |
local outdirUser="$outdir/user" | |
local outdirGlobal="$outdir/global" | |
local filesdone=0 | |
local filecount=0 | |
local filestotal=0 | |
local globals=0 | |
function cleanOutdirs { | |
[[ ! -d $HOME/defaults ]] && mkdir "$HOME/defaults" | |
if [[ -d $outdirApple ]]; then | |
echo "removing all files in $outdirApple" | |
rm -rf "${outdirApple/*}" | |
else | |
mkdir "$outdirApple" | |
fi | |
if [[ -d $outdirUser ]]; then | |
echo "removing all files in $outdirUser" | |
rm -rf "${outdirUser/*}" | |
else | |
mkdir "$outdirUser" | |
fi | |
if [[ -d $outdirGlobal ]]; then | |
echo "removing all files in $outdirGlobal" | |
rm -rf "${outdirGlobal/*}" | |
else | |
mkdir "$outdirGlobal" | |
fi | |
} | |
function exportDomains { | |
filesdone=0 | |
filecount=0 | |
for domain in "${domains[@]}"; do | |
plist="${domain//,/}.plist" | |
if [[ $globals == 0 ]]; then | |
if [[ $domain =~ com.apple ]]; then | |
defaults export "$domain" "$outdirApple/$plist" | |
#echo "writing $plist to $outdirApple" | |
filecount=$((filecount+1)) | |
else | |
defaults export "$domain" "$outdirUser/$plist" | |
#echo "writing $plist to $outdirUser" | |
filecount=$((filecount+1)) | |
fi | |
else | |
sudo defaults export "$domain" "$outdirGlobal/$plist" | |
#echo "writing $plist to $outdirGlobal" | |
filecount=$((filecount+1)) | |
fi | |
filesleft=$((filesleft-1)) | |
filesdone=$((filesdone+1)) | |
echo -ne "[ $filesdone/$filesleft ] \r" | |
done | |
} | |
cleanOutdirs | |
# ------------------------------------------------- | |
local domains=($(defaults domains)) | |
local filesleft=${#domains[@]} | |
echo "USER namespace has ${#domains[@]} domains, exportig..." | |
exportDomains | |
echo "written $filecount files in $outdir" | |
local filestotal=$((filestotal+filecount)) | |
# ------------------------------------------------- | |
globals=1 | |
# ------------------------------------------------- | |
local domains=($(sudo defaults domains)) | |
local filesleft=${#domains[@]} | |
echo "GLOBAL namespace has ${#domains[@]} domains, exportig..." | |
exportDomains | |
echo "written $filecount files in $outdir" | |
local filestotal=$((filestotal+filecount)) | |
# ------------------------------------------------- | |
sudo chown -R "$(whoami)":staff "$HOME/defaults" | |
local timed="$((SECONDS / 3600))hrs $(((SECONDS / 60) % 60))min $((SECONDS % 60))sec" | |
echo "exported $filestotal files in $timed" | |
} | |
exportDefaults |
I've added a line to create a zip file of the defaults
directory, so that it's easy to move it between macOS systems:
#!/usr/bin/env bash
function exportDefaults {
local outdir="$HOME/defaults"
local outdirApple="$outdir/apple"
local outdirUser="$outdir/user"
local outdirGlobal="$outdir/global"
local filesdone=0
local filecount=0
local filestotal=0
local globals=0
function cleanOutdirs {
[[ ! -d $outdir ]] && mkdir "$outdir"
if [[ -d $outdirApple ]]; then
echo "removing all files in $outdirApple"
rm -rf "${outdirApple/*}"
else
mkdir "$outdirApple"
fi
if [[ -d $outdirUser ]]; then
echo "removing all files in $outdirUser"
rm -rf "${outdirUser/*}"
else
mkdir "$outdirUser"
fi
if [[ -d $outdirGlobal ]]; then
echo "removing all files in $outdirGlobal"
rm -rf "${outdirGlobal/*}"
else
mkdir "$outdirGlobal"
fi
}
function exportDomains {
filesdone=0
filecount=0
for domain in "${domains[@]}"; do
plist="${domain}.plist"
if [[ $globals == 0 ]]; then
if [[ $domain =~ com.apple ]]; then
defaults export "$domain" "$outdirApple/$plist"
#echo "writing $plist to $outdirApple"
filecount=$((filecount+1))
else
defaults export "$domain" "$outdirUser/$plist"
#echo "writing $plist to $outdirUser"
filecount=$((filecount+1))
fi
else
sudo defaults export "$domain" "$outdirGlobal/$plist"
#echo "writing $plist to $outdirGlobal"
filecount=$((filecount+1))
fi
filesleft=$((filesleft-1))
filesdone=$((filesdone+1))
echo -ne "[ $filesdone/$filesleft ] \r"
done
}
cleanOutdirs
# -------------------------------------------------
local domainsWithSeparator="$(defaults domains)"
local domains=(${domainsWithSeparator//,/})
local filesleft=${#domains[@]}
echo "USER namespace has ${#domains[@]} domains, exportig..."
exportDomains
echo "written $filecount files in $outdir"
local filestotal=$((filestotal+filecount))
# -------------------------------------------------
globals=1
# -------------------------------------------------
local domainsWithSeparator="$(sudo defaults domains)"
local domains=(${domainsWithSeparator//,/})
local filesleft=${#domains[@]}
echo "GLOBAL namespace has ${#domains[@]} domains, exportig..."
exportDomains
echo "written $filecount files in $outdir"
local filestotal=$((filestotal+filecount))
# -------------------------------------------------
sudo chown -R "$(whoami)":staff "$outdir"
cd "$outdir"
zip -q -r defaults.zip .
local timed="$((SECONDS / 3600))hrs $(((SECONDS / 60) % 60))min $((SECONDS % 60))sec"
echo "exported $filestotal files in $timed"
}
exportDefaults
And here's the corresponding defaults-import.sh
:
#!/usr/bin/env bash
function importDefaults {
local zipPath=$1
local extractDir="$HOME/defaults"
local appleDir="$extractDir/apple"
local userDir="$extractDir/user"
local globalDir="$extractDir/global"
local filesTotal=0
function importDomains {
local dir=$1
local filesImported=0
local filesCount=$(ls -1 "$dir"/*.plist 2>/dev/null | wc -l)
local filesRemaining=$filesCount
local dirName=$(basename "$dir")
echo "$dirName namespace has $filesCount files, importing..."
for plist in "$dir"/*.plist; do
domain=$(basename "$plist" .plist)
if [[ $dir == "$globalDir" ]]; then
sudo defaults import "$domain" "$plist"
else
defaults import "$domain" "$plist"
fi
filesRemaining=$((filesRemaining-1))
filesImported=$((filesImported+1))
echo -ne "[ $filesImported/$filesRemaining ] \r"
done
filesTotal=$((filesTotal+filesCount))
echo -e "Imported $filesCount files from the $dirName namespace.\n"
}
if [[ -d "$extractDir" && -n "$(ls -A "$extractDir")" ]]; then
echo "The extraction directory '$extractDir' is not empty."
read -p "Do you want to delete the directory and continue? (y/N): " confirmDelete
if [[ $confirmDelete == [Yy] ]]; then
rm -rf "$extractDir"
echo -e "Deleted the existing directory '$extractDir'.\n"
else
echo "Script canceled. Exiting..."
exit 0
fi
fi
# Extract the zip file
unzip -q "$zipPath" -d "$extractDir"
# Import plist files in the apple directory
importDomains "$appleDir"
# Import plist files in the user directory
importDomains "$userDir"
# Import plist files in the global directory
importDomains "$globalDir"
echo "Defaults import completed. Imported a total of $filesTotal files."
}
if [ -z "$1" ]; then
echo "Please provide the path to the zip file."
else
importDefaults "$1"
fi
The import script requires the path to the zip file as first parameter.
E.g. defaults-import.sh ~/Downloads/defaults.zip
Excellent! Thanks for updating this
@inoperable My pleasure! Thank you for providing this script in the first place.
One thing I didnt seen before /usr/env/bash could be trouble since Apple dropped bash in favour of zsh (unless that changed back, I dropped macOS since Apple Silicon showed up - main reason being economics)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi, this is exactly what I was looking for! How do you import the settings? Thank you
Edit: I guess it's
default import <domain> <path to plist>
, right? :-)