/home/alex/dev/lib/os.sh (1)
# ------------------------------------------------------------------------------
# os.sh
# =====
#
# Project Library
# Scope macOS
# Copyright (C) 2024 by RaySoft, Zurich, Switzerland
# License GNU General Public License (GPL) 2.0
# https://www.gnu.org/licenses/gpl2.txt
#
# ------------------------------------------------------------------------------
#
# WARNING: This library uses functions from the 'nf.sh' library!
#
# ------------------------------------------------------------------------------
# Exit if the library is run as a script and not sourced as a library
if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
echo "Don't run this script! Just source it."
exit 1
fi
# Return if the library is already loaded
if declare -F 'os' >'/dev/null' 2>&1; then
return 0
fi
# Return if a needed library is not loaded
for lib in 'nf'; do
if ! declare -F "${lib}" >'/dev/null' 2>&1; then
echo "The needed library '${lib}.sh' is not loaded!"
return 1
fi
done
# ------------------------------------------------------------------------------
os() {
# Show all function of this library.
#
# Arguments:
# none
#
# Returns:
# 0: Success
# >0: Error
nf::print_heading '-' 'ba' "My 'Operating System' Library"
# Print all functions starting with the prefix 'xx::' but ignore private
# functions with the prefix 'xx::_'
compgen -c "${FUNCNAME[0]}::" | grep -v "${FUNCNAME[0]}::_"
echo
return 0
}
# ------------------------------------------------------------------------------
os::change_space() {
# Change the space in macOS.
#
# NOTE: This only works if Switch to Desktop [1-6] is activated in
# System Preferences => Keyboard => Shortcuts
#
# Arguments:
# $1: Space number [1-6], start counting by 1
#
# Returns:
# 0: Success
# >0: Error
# Return if the function was called incorrectly
if [[ "$#" -ne 1 || ! "$1" =~ ^[1-6]$ ]]; then
nf::carp "Error calling function: $*!"
return 1
fi
local bin=''
# Return if a needed binary is not available
for bin in 'osascript'; do
if ! type -P "${bin}" >'/dev/null' 2>&1; then
nf::carp "Error finding binary: ${bin}!"
return 1
fi
done
# Define a local variable
local key=18
# Get the key for a certain space
case "$1" in
1) key=18 ;;
2) key=19 ;;
3) key=20 ;;
4) key=21 ;;
5) key=23 ;; # This is not an error!
6) key=22 ;;
esac
# Run the AppleScript to perform the key stroke
if ! osascript <<-EOS ; then
tell application "System Events"
key code ${key} using {control down}
end tell
delay 0.1
EOS
nf::carp 'Error running AppleScript!'
return 1
fi
return 0
}
# ------------------------------------------------------------------------------
os::mkdir_ifn() {
# Make directories if they do not exist.
#
# Arguments:
# $@: List of directories
#
# Returns:
# 0: Success
# >0: Error
# Define local variables
local path=''
# For all directories
for path in "$@"; do
# If the directory doesn't exist
if [[ ! -d "${path}" ]]; then
# Continue if a file with this name already exist
if [[ -e "${path}" ]]; then
nf::carp "File already exists: ${path}!"
continue
fi
# Make the directory and if needed its parent directories
if ! mkdir -p "${path}"; then
nf::carp "Error making directory: ${path}!"
return 1
fi
fi
done
return 0
}
# ------------------------------------------------------------------------------
os::run_in_iterm() {
# Opens a new iTerm window and runs the given command.
#
# Arguments:
# $@: Command with parameters
#
# Returns:
# 0: Success
# >0: Error
#
# Example:
# os::run_in_iterm ssh 'alex@raysoft.loc'
# Returns if the function was called incorrectly
if [[ "$#" -eq 0 ]]; then
nf::carp 'Error calling function!'
return 1
fi
local bin=''
# Returns if a needed binary is not available
for bin in 'osascript'; do
if ! type -P "${bin}" >'/dev/null' 2>&1; then
nf::carp "Error finding binary: ${bin}!"
return 1
fi
done
# Runs the AppleScript to open a new iTerm windows and executes the 'tail'
# command in it
if ! osascript <<-EOS >'/dev/null' 2>&1; then
tell application "iTerm"
set newWindow to (create window with default profile)
tell newWindow
tell current session of newWindow to write text "$*"
end tell
end tell
EOS
nf::carp 'Error running AppleScript!'
return 1
fi
return 0
}
# ------------------------------------------------------------------------------
os::set_permissions() {
# Set permissions for a list of files or directories.
#
# Arguments:
# $1: Owner's user
# $2: Owner's group
# $3: Permissions for files
# $4: Permissions for directories
# $@: List of files or directories
#
# Returns:
# 0: Success
# >0: Error
#
# Example:
# os::set_permissions 'alex' 'users' 0600 0700 "${HOME}"
# Return if the function was called incorrectly
if [[ "$#" -lt 5 || ! "$1" =~ ^[a-z][-a-z0-9]*$ || ! "$2" =~ ^[a-z][-a-z0-9]*$ \
|| ! "$3" =~ ^[0-7]{3,4}$ || ! "$4" =~ ^[0-7]{3,4}$ ]]
then
nf::carp "Error calling function: $*!"
return 1
fi
# Define local variables
local path=''
# For all files or directories
for path in "${@:5}"; do
# Return if the file or directory doesn't exist
if [[ ! -e "${path}" ]]; then
nf::carp "Error finding directory: ${path}!"
continue
fi
# Search for all files and directories, check if the owner and file
# permissions are correct and adjust them if necessary
if ! find "${path}" \
'!' '(' -user "$1" -group "$2" ')' \
-execdir sudo chown "$1.$2" '{}' '+' \
-printf "Changing owner for %p from %u.%g to $1.$2\\n" \
',' \
-type 'f' '(' \
'!' -perm "$3" \
-execdir sudo chmod "$3" '{}' '+' \
-printf "Changing mode for %p from %#m to $3\\n" \
')' \
-or -type 'd' '(' \
'!' -perm "$4" \
-execdir sudo chmod "$4" '{}' '+' \
-printf "Changing mode for %p from %#m to $4\\n" \
')'
then
nf::carp "Error changing permissions: ${path}!"
return 1
fi
done
return 0
}
# ------------------------------------------------------------------------------
os::test_env() {
# Test the environment set by the calling script by validating the variables
# and making them read only.
#
# Arguments:
# $1: Variable prefix
#
# Returns:
# 0: Success
# >0: Error
# Return if the function was called incorrectly
if [[ "$#" -ne 1 && ! "$1" =~ ^[A-Z]+$ ]]; then
nf::carp "Error calling function: $*!"
return 1
fi
local name=''
local var=''
while read -r name; do
if [[ "${name}" =~ ^$1_[DF]._ ]]; then
local array="${name}[@]"
for var in "${!array}"; do
if [[ "${name}" =~ ^$1_DE_ && ! -d "${var}" ]]; then
nf::carp "Error finding directory: ${var}!"
return 1
elif [[ "${name}" =~ ^$1_DN_ && ! -d "${var}" ]]; then
if ! os::mkdir_ifn "${var}"; then
return 1
fi
elif [[ "${name}" =~ ^$1_FE_ && ! -f "${var}" ]]; then
nf::carp "Error finding file: ${var}!"
return 1
fi
done
elif [[ "${name}" =~ ^$1_X_ ]]; then
if [[ ! ( -f "${!name[0]}" && -x "${!name[0]}" ) ]]; then
nf::carp "Error finding executable: ${!name[0]}!"
return 1
fi
fi
if ! declare -r "${name}" >'/dev/null' 2>&1; then
nf::carp "Error setting variable to read only: ${name}!"
return 1
fi
done < <(compgen -v "$1_")
return 0
}
# ------------------------------------------------------------------------------
return 0
Usage
NOTE:
This script uses functions from the library ~/dev/lib/nf.sh.
# Path to the global libraries
XX_DE_GLOBAL_LIB="${HOME}/dev/lib"
# Global libraries to be loaded
XX_GLOBAL_LIBS=('nf' 'os')
# Test if library path is available
if [[ ! -d "${XX_DE_GLOBAL_LIB}" ]]; then
echo "Error finding directory: ${XX_DE_GLOBAL_LIB}!"
exit 1
fi
# Load libraries
for lib in "${XX_GLOBAL_LIBS[@]}"; do
lib="${XX_DE_GLOBAL_LIB}/${lib}.sh"
if [[ ! -f "${lib}" ]]; then
echo "Error finding library: ${lib}!"
exit 1
fi
if ! source "${lib}"; then
exit 1
fi
done