171 lines
4.6 KiB
Bash
171 lines
4.6 KiB
Bash
#!/bin/bash
|
|
# Ver: 1.3 by Endial Fang (endial@126.com)
|
|
#
|
|
# 文件管理函数库
|
|
|
|
# 加载依赖项
|
|
source "/usr/local/lib/liblog.sh"
|
|
|
|
# 函数列表
|
|
|
|
# 确保指定的 文件/路径 所属权为指定的 用户/组
|
|
# 参数:
|
|
# $1 - 文件路径
|
|
# $2 - 用户
|
|
# $3 - 用户组
|
|
ensure_owned_by() {
|
|
local path="${1:?path is missing}"
|
|
local owner="${2:?owner is missing}"
|
|
local group="${3:-}"
|
|
|
|
if [[ -n $group ]]; then
|
|
chown "$owner":"$group" "$path"
|
|
else
|
|
chown "$owner":"$owner" "$path"
|
|
fi
|
|
}
|
|
|
|
# 检测目录是否存在,如果不存在则创建,同时修改为指定的用户
|
|
# 参数:
|
|
# $1 - 目录路径
|
|
# $2 - 用户
|
|
# $3 - 用户组
|
|
ensure_dir_exists() {
|
|
local dir="${1:?directory is missing}"
|
|
local owner_user="${2:-}"
|
|
local owner_group="${3:-}"
|
|
|
|
[ -d "${dir}" ] || mkdir -p "${dir}"
|
|
if [[ -n $owner_user ]]; then
|
|
ensure_owned_by "$dir" "$owner_user" "$owner_group"
|
|
fi
|
|
}
|
|
|
|
# 检测目录是否存在或为空
|
|
# 参数:
|
|
# $1 - 目录路径
|
|
is_dir_empty() {
|
|
local dir="${1:?missing directory}"
|
|
|
|
# 计算真实路径,避免符号链接问题
|
|
local -r dir="$(realpath "$path")"
|
|
if [[ ! -e "$dir" ]] || [[ -z "$(ls -A "$dir")" ]]; then
|
|
true
|
|
else
|
|
false
|
|
fi
|
|
}
|
|
|
|
# 检测挂载的路径是否存在或为空
|
|
# 参数:
|
|
# $1 - 文件或路径
|
|
is_mounted_dir_empty() {
|
|
local dir="${1:?missing directory}"
|
|
|
|
if is_dir_empty "$dir" || find "$dir" -mindepth 1 -maxdepth 1 -not -name ".snapshot" -not -name "lost+found" -exec false {} +; then
|
|
true
|
|
else
|
|
false
|
|
fi
|
|
}
|
|
|
|
# 检测指定的路径当前用户是否可写入
|
|
# 参数:
|
|
# $1 - 文件或路径
|
|
is_writable() {
|
|
local file="${1:?missing file}"
|
|
local dir
|
|
dir="$(dirname "$file")"
|
|
|
|
if [[ (-f "$file" && -w "$file") || (! -f "$file" && -d "$dir" && -w "$dir") ]]; then
|
|
true
|
|
else
|
|
false
|
|
fi
|
|
}
|
|
|
|
# 生成相对路径
|
|
# 参数:
|
|
# $1 - 路径
|
|
# $2 - 基准路径
|
|
relativize() {
|
|
local -r path="${1:?missing path}"
|
|
local -r base="${2:?missing base}"
|
|
|
|
pushd "$base" >/dev/null || exit
|
|
realpath -q --no-symlinks --relative-base="$base" "$path" | sed -e 's|^/$|.|' -e 's|^/||'
|
|
popd >/dev/null || exit
|
|
}
|
|
|
|
# 循环设置目录中子目录及文件权限
|
|
# 参数:
|
|
# $1 - paths (as a string).
|
|
# Flags:
|
|
# -f|--file-mode - 文件权限模式
|
|
# -d|--dir-mode - 目录权限模式
|
|
# -u|--user - 用户
|
|
# -g|--group - 用户组
|
|
configure_permissions_ownership() {
|
|
local -r paths="${1:?paths is missing}"
|
|
local dir_mode=""
|
|
local file_mode=""
|
|
local user=""
|
|
local group=""
|
|
|
|
# 参数有效性校验
|
|
shift 1
|
|
while [ "$#" -gt 0 ]; do
|
|
case "$1" in
|
|
-f|--file-mode)
|
|
shift
|
|
file_mode="${1:?missing mode for files}"
|
|
;;
|
|
-d|--dir-mode)
|
|
shift
|
|
dir_mode="${1:?missing mode for directories}"
|
|
;;
|
|
-u|--user)
|
|
shift
|
|
user="${1:?missing user}"
|
|
;;
|
|
-g|--group)
|
|
shift
|
|
group="${1:?missing group}"
|
|
;;
|
|
*)
|
|
error "Invalid command line flag $1" >&2
|
|
return 1
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
read -r -a filepaths <<< "$paths"
|
|
for p in "${filepaths[@]}"; do
|
|
if [[ -e "$p" ]]; then
|
|
debug "Check $p"
|
|
find -L "$p" -printf ""
|
|
if [[ -n ${dir_mode} ]]; then
|
|
debug "Change permissions to ${dir_mode} of directories in $p"
|
|
find -L "$p" -type d ! -perm "$dir_mode" -print0 | xargs -r -0 chmod "$dir_mode"
|
|
fi
|
|
if [[ -n ${file_mode} ]]; then
|
|
debug "Change permissions to ${file_mode} of files in $p"
|
|
find -L "$p" -type f ! -perm "$file_mode" -print0 | xargs -r -0 chmod "$file_mode"
|
|
fi
|
|
if [[ -n $user ]] && [[ -n ${group} ]]; then
|
|
debug "Change ownership to ${user}:${group} of files and directories in $p"
|
|
find -L "$p" -print0 | xargs -r -0 chown "${user}:${group}"
|
|
elif [[ -n $user ]] && [[ -z $group ]]; then
|
|
debug "Change user to ${user} of files and directories in $p"
|
|
find -L "$p" -print0 | xargs -r -0 chown "${user}"
|
|
elif [[ -z $user ]] && [[ -n $group ]]; then
|
|
debug "Change group to ${group} of files and directories in $p"
|
|
find -L "$p" -print0 | xargs -r -0 chgrp "${group}"
|
|
fi
|
|
else
|
|
error "$p does not exist"
|
|
fi
|
|
done
|
|
}
|