797 lines
18 KiB
Bash
797 lines
18 KiB
Bash
#!/bin/bash
|
||
# shellcheck disable=SC2155
|
||
if ! type "include" > /dev/null 2>&1; then
|
||
include() {
|
||
. "$(cd "$(dirname "$1")" && pwd)/${2}";
|
||
};
|
||
fi
|
||
include "${BASH_SOURCE[0]}" ../pragma_once.bash
|
||
if ! pragma_once ${BASH_SOURCE[0]}; then return 0; fi
|
||
include "${BASH_SOURCE[0]}" ./global_rely/export.bash
|
||
# shellcheck source=./global_rely/export.bash
|
||
|
||
|
||
|
||
# 这种是为了语法提示
|
||
# shellcheck source=./global_rely/log.bash
|
||
# shellcheck source=./global_rely/stack_trace.bash
|
||
|
||
|
||
check_baidu_network() {
|
||
local baidu_domain="www.baidu.com" # 要检测的目标域名
|
||
echo "正在检测是否能连接到 $baidu_domain..."
|
||
|
||
# 使用 ping 命令检测是否能连接到 baidu.com
|
||
if ping -c 1 "$baidu_domain" > /dev/null 2>&1; then
|
||
echo "$baidu_domain 网络连接正常。"
|
||
return 0 # 连接正常
|
||
else
|
||
echo "无法连接到 $baidu_domain,网络不可达。"
|
||
return 1 # 网络不可达
|
||
fi
|
||
}
|
||
|
||
# 用法:
|
||
# chromium_net_check_report # 检测一次并输出报告
|
||
# chromium_net_check_report --wait # 循环等待,直到“任一方式可用”为止,并持续输出报告
|
||
# chromium_net_check_report --wait 300 # 最多等待 300 秒
|
||
#
|
||
# 报告包含:
|
||
# 1) DNS 解析是否成功
|
||
# 2) ping(ICMP) 是否通(注意:TUN/代理下可能一直不通)
|
||
# 3) curl HTTPS HEAD 是否通(更贴近实际拉代码/访问网页)
|
||
#
|
||
chromium_net_check_report() {
|
||
local host="chromium.googlesource.com"
|
||
local wait_mode=0
|
||
local timeout=0
|
||
|
||
if [[ "${1:-}" == "--wait" ]]; then
|
||
wait_mode=1
|
||
timeout="${2:-0}" # 0 = 无限等
|
||
fi
|
||
|
||
# ping 参数兼容:Windows (MSYS/Git-Bash) 用 -n/-w(ms),Linux/macOS 用 -c/-W(s)
|
||
local ping_count_flag="-c"
|
||
local ping_timeout_flag="-W"
|
||
local ping_timeout_val="1"
|
||
case "$(uname -s 2>/dev/null | tr '[:upper:]' '[:lower:]')" in
|
||
mingw*|msys*|cygwin*)
|
||
ping_count_flag="-n"
|
||
ping_timeout_flag="-w"
|
||
ping_timeout_val="1000" # ms
|
||
;;
|
||
esac
|
||
|
||
_ts() {
|
||
date "+%Y-%m-%d %H:%M:%S" 2>/dev/null || echo ""
|
||
}
|
||
|
||
_dns_check() {
|
||
# 尽量不用 nslookup 输出噪音:只判断能不能解析出 IP
|
||
if command -v getent >/dev/null 2>&1; then
|
||
getent hosts "$host" >/dev/null 2>&1
|
||
return $?
|
||
elif command -v nslookup >/dev/null 2>&1; then
|
||
nslookup "$host" >/dev/null 2>&1
|
||
return $?
|
||
else
|
||
return 127
|
||
fi
|
||
}
|
||
|
||
_ping_check() {
|
||
ping "${ping_count_flag}" 1 "${ping_timeout_flag}" "${ping_timeout_val}" "$host" >/dev/null 2>&1
|
||
return $?
|
||
}
|
||
|
||
_curl_check() {
|
||
if ! command -v curl >/dev/null 2>&1; then
|
||
return 127
|
||
fi
|
||
curl -fsSI --max-time 6 "https://${host}/" >/dev/null 2>&1
|
||
return $?
|
||
}
|
||
|
||
_one_report() {
|
||
local dns_rc ping_rc curl_rc
|
||
local dns_status ping_status curl_status
|
||
local hint=()
|
||
|
||
dns_rc=0; ping_rc=0; curl_rc=0
|
||
|
||
_dns_check; dns_rc=$?
|
||
_ping_check; ping_rc=$?
|
||
_curl_check; curl_rc=$?
|
||
|
||
case "$dns_rc" in
|
||
0) dns_status="OK" ;;
|
||
127) dns_status="N/A(no nslookup/getent)" ;;
|
||
*) dns_status="FAIL" ;;
|
||
esac
|
||
|
||
case "$ping_rc" in
|
||
0) ping_status="OK" ;;
|
||
*) ping_status="FAIL" ;;
|
||
esac
|
||
|
||
case "$curl_rc" in
|
||
0) curl_status="OK" ;;
|
||
127) curl_status="N/A(no curl)" ;;
|
||
*) curl_status="FAIL" ;;
|
||
esac
|
||
|
||
echo "==================== Chromium Network Report ===================="
|
||
echo "Time: $(_ts)"
|
||
echo "Host: ${host}"
|
||
echo "------------------------------------------------------------------"
|
||
echo "DNS : ${dns_status}"
|
||
echo "PING : ${ping_status}"
|
||
echo "CURL : ${curl_status} (HTTPS HEAD https://${host}/)"
|
||
echo "------------------------------------------------------------------"
|
||
|
||
# 解释/建议(按组合给)
|
||
if [[ "$dns_rc" != 0 && "$dns_rc" != 127 ]]; then
|
||
hint+=("DNS 解析失败:检查系统 DNS/Clash DNS 设置,或是否被劫持/污染。")
|
||
fi
|
||
|
||
if [[ "$curl_rc" == 0 ]]; then
|
||
hint+=("HTTPS 可访问:用于 gclient/git 拉取通常已经足够。")
|
||
else
|
||
if [[ "$curl_rc" == 127 ]]; then
|
||
hint+=("未检测到 curl:建议安装/启用 curl(Git-Bash 通常自带)。")
|
||
else
|
||
hint+=("HTTPS 不可访问:通常表示代理/TUN 未生效或证书/网络被拦。")
|
||
fi
|
||
fi
|
||
|
||
if [[ "$ping_rc" != 0 ]]; then
|
||
hint+=("PING 不通:在 Clash TUN/代理下可能正常(ICMP 常被丢弃)。不要只以 ping 为唯一标准。")
|
||
fi
|
||
|
||
if [[ "${#hint[@]}" -gt 0 ]]; then
|
||
echo "Notes:"
|
||
local i
|
||
for i in "${hint[@]}"; do
|
||
echo " - $i"
|
||
done
|
||
fi
|
||
|
||
echo "=================================================================="
|
||
|
||
# 返回码策略:
|
||
# 0 = curl OK(认为网络可用)
|
||
# 1 = curl FAIL(不可用)
|
||
if [[ "$curl_rc" == 0 ]]; then
|
||
return 0
|
||
fi
|
||
return 1
|
||
}
|
||
|
||
if [[ "$wait_mode" -eq 0 ]]; then
|
||
_one_report
|
||
return $?
|
||
fi
|
||
|
||
local start_ts now_ts elapsed
|
||
start_ts=$(date +%s 2>/dev/null || echo 0)
|
||
|
||
echo "[WAIT] 循环检测中:直到 CURL 可访问为止(timeout=${timeout}s,0=无限)"
|
||
while true; do
|
||
if _one_report; then
|
||
echo "[DONE] CURL 已可访问:网络就绪"
|
||
return 0
|
||
fi
|
||
|
||
if [[ "$timeout" -gt 0 && "$start_ts" -ne 0 ]]; then
|
||
now_ts=$(date +%s 2>/dev/null || echo 0)
|
||
elapsed=$((now_ts - start_ts))
|
||
if [[ "$elapsed" -ge "$timeout" ]]; then
|
||
echo "[TIMEOUT] 等待超过 ${timeout}s,仍不可访问 https://${host}/"
|
||
return 2
|
||
fi
|
||
fi
|
||
|
||
sleep 3
|
||
done
|
||
}
|
||
|
||
|
||
|
||
|
||
print_important_var() {
|
||
local var=$1 # 传入的变量名
|
||
local val=${!var} # 使用 eval 来获取变量的值
|
||
echo "【${var}】=== 【${val}】"
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
load_PATH(){
|
||
local tmp
|
||
merge_args tmp ":" "$@"
|
||
export PATH="${tmp}${PATH:+:$PATH}"
|
||
}
|
||
|
||
load_LIBRARY_PATH(){
|
||
local tmp
|
||
merge_args tmp ":" "$@"
|
||
export LIBRARY_PATH="${tmp}${LIBRARY_PATH:+:$LIBRARY_PATH}"
|
||
}
|
||
|
||
load_LD_LIBRARY_PATH(){
|
||
local tmp
|
||
merge_args tmp ":" "$@"
|
||
export LD_LIBRARY_PATH="${tmp}${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
|
||
}
|
||
|
||
load_ALL(){
|
||
load_PATH "$@"
|
||
load_LIBRARY_PATH "$@"
|
||
load_LD_LIBRARY_PATH "$@"
|
||
}
|
||
save_env() {
|
||
export saved_PATH="$PATH"
|
||
export saved_LIBRARY_PATH="$LIBRARY_PATH"
|
||
export saved_LD_LIBRARY_PATH="$LD_LIBRARY_PATH"
|
||
}
|
||
|
||
restore_env() {
|
||
export PATH="$saved_PATH"
|
||
export LIBRARY_PATH="$saved_LIBRARY_PATH"
|
||
export LD_LIBRARY_PATH="$saved_LD_LIBRARY_PATH"
|
||
}
|
||
|
||
# 公用函数:打印指定环境变量的路径
|
||
print_env_path() {
|
||
local env_var="$1" # 环境变量名
|
||
local env_value="${!env_var}" # 获取环境变量的值
|
||
# 输出环境变量的路径
|
||
log_info "[ $env_var ]:"
|
||
IFS=":" read -r -a paths <<< "$env_value"
|
||
i=0
|
||
for path in "${paths[@]}"; do
|
||
# 使用 printf 格式化 $i,确保它是 3 位,右对齐
|
||
formatted_i=$(printf "%2d" "$i")
|
||
log_info "$formatted_i: $path"
|
||
((i++)) || true
|
||
done
|
||
}
|
||
|
||
|
||
print_env() {
|
||
log_trace "========================== 【 打印环境变量 】 =========================="
|
||
print_env_path "PATH"
|
||
print_env_path "LD_LIBRARY_PATH"
|
||
print_env_path "LD_RUN_PATH"
|
||
print_env_path "LIBRARY_PATH"
|
||
log_trace "========================== 【 打印环境变量 】 =========================="
|
||
}
|
||
|
||
|
||
print_remain_args(){
|
||
local err=$1
|
||
shift 1
|
||
local i=0
|
||
log_error "msg:${err}"
|
||
for param in "$@"; do
|
||
log_error "[%2d] $param" $i
|
||
((i++))
|
||
done
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
# 使用方式
|
||
# if pragma_once "${BASH_SOURCE[0]}"; then
|
||
# fi
|
||
|
||
|
||
|
||
|
||
|
||
centos7_6_init_iso_root() {
|
||
sudo yum --disablerepo=* --enablerepo=wyc groupinstall "Development Tools" -y
|
||
sudo yum --disablerepo=* --enablerepo=wyc install gmp-devel mpfr-devel libmpc-devel openssl mesa-libGL-devel -y
|
||
}
|
||
|
||
|
||
check_directory() {
|
||
local dir="$1"
|
||
if [ ! -d "$dir" ]; then
|
||
echo "错误: 目录不存在: $dir"
|
||
return 1
|
||
fi
|
||
return 0
|
||
}
|
||
|
||
check_directory_var() {
|
||
local var_name="$1"
|
||
local dir="${!var_name}"
|
||
|
||
if [ -z "$var_name" ]; then
|
||
echo "错误: 未传入变量名"
|
||
return 1
|
||
fi
|
||
|
||
if [ -z "$dir" ]; then
|
||
echo "错误: 变量未定义或为空: $var_name"
|
||
return 1
|
||
fi
|
||
|
||
if [ ! -d "$dir" ]; then
|
||
echo "错误: 目录不存在: $var_name=$dir"
|
||
return 1
|
||
fi
|
||
|
||
return 0
|
||
}
|
||
|
||
|
||
|
||
check_file() {
|
||
local file="$1"
|
||
if [ ! -f "$file" ]; then
|
||
echo "错误: 文件不存在: $file"
|
||
return 1
|
||
fi
|
||
return 0
|
||
}
|
||
|
||
check_file_ex() {
|
||
local prefix="$1"
|
||
local file="$2"
|
||
if [ ! -f "$file" ]; then
|
||
echo "【${prefix}】 错误: 文件不存在: $file"
|
||
return 1
|
||
fi
|
||
return 0
|
||
}
|
||
|
||
check_file_var() {
|
||
local var_name="$1"
|
||
local file="${!var_name}"
|
||
|
||
if [ -z "$var_name" ]; then
|
||
echo "错误: 未传入变量名"
|
||
return 1
|
||
fi
|
||
|
||
if [ -z "$file" ]; then
|
||
echo "错误: 变量未定义或为空: $var_name"
|
||
return 1
|
||
fi
|
||
|
||
if [ ! -f "$file" ]; then
|
||
echo "错误: 文件不存在: $var_name=$file"
|
||
return 1
|
||
fi
|
||
|
||
return 0
|
||
}
|
||
|
||
is_absolute_directory() {
|
||
local dir_path="$1"
|
||
if [[ "$dir_path" != /* ]] || [ ! -d "$dir_path" ]; then
|
||
return 1
|
||
fi
|
||
return 0
|
||
}
|
||
|
||
is_absolute_file() {
|
||
local file_path="$1"
|
||
if [[ "$file_path" != /* ]] || [ ! -f "$file_path" ]; then
|
||
return 1
|
||
fi
|
||
return 0
|
||
}
|
||
|
||
is_absolute_elf() {
|
||
local path="$1"
|
||
if [[ "$path" != /* ]]; then
|
||
echo "Not an absolute path: $path"
|
||
return 1
|
||
fi
|
||
if [[ ! -f "$path" ]]; then
|
||
echo "File not found: $path"
|
||
return 1
|
||
fi
|
||
if ! file "$path" | grep -q 'ELF'; then
|
||
echo "Not an ELF file: $path"
|
||
return 1
|
||
fi
|
||
return 0
|
||
}
|
||
|
||
is_valid_absolute_path_format() {
|
||
local input="$1"
|
||
if [[ "$input" =~ ^(/[^:/]+)+(:/[^:/]+)+$ ]]; then
|
||
return 0
|
||
fi
|
||
echo "Invalid format: $input"
|
||
return 1
|
||
}
|
||
|
||
#!/bin/bash
|
||
|
||
# 压缩函数:将目录压缩为 .tar.gz 格式
|
||
compress_directory_tar_gz() {
|
||
local source_dir="$1" # 源目录
|
||
local install_root="$2" # 目标目录
|
||
local archive_name="$3" # 压缩包名称
|
||
if [ ! -d "$source_dir" ]; then
|
||
echo "compress_directory Error: Source directory '$source_dir' does not exist!"
|
||
return 1
|
||
fi
|
||
echo "Compressing '$source_dir' to '$install_root/$archive_name'..."
|
||
# 去除硬链接
|
||
# local workdir="$(dirname "$source_dir")"
|
||
# local a2="$(basename "$source_dir")"
|
||
tar --hard-dereference -czvf "$install_root/$archive_name" -C "${source_dir}" .
|
||
|
||
if [ $? -eq 0 ]; then
|
||
echo "Compression successful! $install_root/$archive_name"
|
||
else
|
||
echo "Compression failed! $install_root/$archive_name"
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
|
||
|
||
|
||
# 解压函数:将 .tar.gz 文件解压到目标目录
|
||
compress_directory_tar_gz_copy() {
|
||
local source_dir="$1"
|
||
local install_root="$2"
|
||
local archive_name="$3"
|
||
|
||
if [ ! -d "$source_dir" ]; then
|
||
echo "compress_directory Error: Source directory '$source_dir' does not exist!"
|
||
return 1
|
||
fi
|
||
|
||
echo "Compressing '$source_dir' to '$install_root/$archive_name'..."
|
||
|
||
tar --dereference --hard-dereference -czvf "$install_root/$archive_name" -C "${source_dir}" .
|
||
|
||
if [ $? -eq 0 ]; then
|
||
echo "Compression successful! $install_root/$archive_name"
|
||
else
|
||
echo "Compression failed! $install_root/$archive_name"
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# 示例用法
|
||
# compress_directory "/path/to/source_directory" "/path/to/your/install_root" "your_archive_name.tar.gz"
|
||
# decompress_archive "/path/to/your/install_root/your_archive_name.tar.gz" "/path/to/target_directory"
|
||
|
||
|
||
# 通用检查函数:检查值是否在给定范围内
|
||
check_value_in_range() {
|
||
local param_name="$1" # 参数名称
|
||
shift # 移除参数名称,剩下的是有效范围
|
||
|
||
# 获取参数的当前值
|
||
local value="${!param_name}"
|
||
|
||
# 遍历所有范围值
|
||
for range_value in "$@"; do
|
||
if [[ "$value" == "$range_value" ]]; then
|
||
return 0 # 找到匹配的值,返回成功
|
||
fi
|
||
done
|
||
|
||
# 如果没有找到匹配值,打印错误并退出
|
||
log_error "ERROR: '$param_name' has invalid value '$value'. Valid values are: $*"
|
||
exit 77
|
||
}
|
||
|
||
check_ret_exit() {
|
||
local ret=$?
|
||
local msg="$1"
|
||
|
||
if (( ret != 0 )); then
|
||
if [[ -z "${msg//[[:space:]]/}" ]]; then
|
||
msg="命令执行失败"
|
||
fi
|
||
log_error "${msg} ret=${ret}"
|
||
exit "$ret"
|
||
fi
|
||
}
|
||
|
||
|
||
clear_dir_contents() {
|
||
local dir="$1"
|
||
|
||
# 参数为空时直接报错返回
|
||
if [[ -z "$dir" ]]; then
|
||
echo "[ERROR] clear_dir_contents: 目录参数不能为空" >&2
|
||
return 1
|
||
fi
|
||
|
||
# 目录不存在时跳过,不报错
|
||
if [[ ! -d "$dir" ]]; then
|
||
echo "[INFO] 目录不存在,跳过清空: $dir"
|
||
return 0
|
||
fi
|
||
|
||
# 删除普通文件和普通目录
|
||
rm -rf "${dir:?}/"*
|
||
|
||
# 删除隐藏文件/目录(例如 .git、.cache),但不匹配 . 和 ..
|
||
rm -rf "${dir:?}/".[!.]*
|
||
|
||
# 删除以两个点开头的隐藏文件/目录,但仍然不会匹配 .. 本身
|
||
rm -rf "${dir:?}/"..?*
|
||
|
||
echo "[OK] 已清空目录内容: $dir"
|
||
}
|
||
|
||
check_and_create_dir_var() {
|
||
local dir_var="$1"
|
||
local dir_path="${!dir_var:-}"
|
||
if [[ -z "$dir_path" ]]; then
|
||
log_error "ERROR: directory variable is empty: %s" "$dir_var"
|
||
return 1
|
||
fi
|
||
if [[ -d "$dir_path" ]]; then
|
||
return 0
|
||
fi
|
||
mkdir -p "$dir_path" || {
|
||
log_error "ERROR: failed to create directory: %s=%s" "$dir_var" "$dir_path"
|
||
return 1
|
||
}
|
||
}
|
||
|
||
check_and_create_dir() {
|
||
local dir="$1"
|
||
if [[ -z "${dir//[[:space:]]/}" ]]; then
|
||
log_error "ERROR: dir is empty"
|
||
return 4
|
||
fi
|
||
if [[ -d "$dir" ]]; then
|
||
return 0
|
||
fi
|
||
mkdir -p "$dir" || {
|
||
log_error "ERROR: failed to create directory: %s" "$dir"
|
||
return 5
|
||
}
|
||
}
|
||
|
||
|
||
|
||
# 使用示例
|
||
# declare -a files
|
||
# regex_glob_files files "/ae/bash/0_git_cache_dir/binutils-gdb" "/ae/bash/0_git_cache_dir/binutils-gdb/build" '.*\.(c|h)$'
|
||
# echo "count: ${#files[@]}"
|
||
# printf '%s\n' "${files[@]}"
|
||
# i=0
|
||
# for f in "${files[@]}"; do
|
||
# printf '%d: %s\n' "$i" "$f"
|
||
# ((i++))
|
||
# done
|
||
|
||
regex_glob_files() {
|
||
if [ $# -lt 4 ]; then
|
||
return 1
|
||
fi
|
||
|
||
local ret_name="$1"
|
||
local include_path="$2"
|
||
local exclude_path="$3"
|
||
local regex_expr="$4"
|
||
|
||
if [ -z "$ret_name" ]; then
|
||
return 1
|
||
fi
|
||
|
||
local -n ret="$ret_name"
|
||
ret=()
|
||
|
||
if [ -z "$include_path" ] || [ ! -e "$include_path" ]; then
|
||
return 0
|
||
fi
|
||
|
||
local include_abs=""
|
||
local exclude_abs=""
|
||
local item=""
|
||
local base_name=""
|
||
|
||
include_abs=$(realpath "$include_path")
|
||
|
||
if [ -n "$exclude_path" ] && [ -e "$exclude_path" ]; then
|
||
exclude_abs=$(realpath "$exclude_path")
|
||
fi
|
||
|
||
if [ -f "$include_abs" ]; then
|
||
if [ -n "$exclude_abs" ] && [ "$include_abs" = "$exclude_abs" ]; then
|
||
return 0
|
||
fi
|
||
|
||
if [ -n "$regex_expr" ]; then
|
||
base_name="${include_abs##*/}"
|
||
if [[ "$base_name" =~ $regex_expr ]]; then
|
||
ret+=("$include_abs")
|
||
fi
|
||
else
|
||
ret+=("$include_abs")
|
||
fi
|
||
|
||
return 0
|
||
fi
|
||
|
||
if [ -d "$include_abs" ]; then
|
||
while IFS= read -r item; do
|
||
if [ -n "$regex_expr" ]; then
|
||
base_name="${item##*/}"
|
||
if [[ "$base_name" =~ $regex_expr ]]; then
|
||
ret+=("$item")
|
||
fi
|
||
else
|
||
ret+=("$item")
|
||
fi
|
||
done < <(
|
||
if [ -n "$exclude_abs" ]; then
|
||
find "$include_abs" \
|
||
\( -path "$exclude_abs" -o -path "$exclude_abs/*" \) -prune -o \
|
||
-type f -print
|
||
else
|
||
find "$include_abs" -type f -print
|
||
fi
|
||
)
|
||
|
||
return 0
|
||
fi
|
||
|
||
return 0
|
||
}
|
||
|
||
|
||
# * 任意长度任意字符(可为0) *.c a.c, test.c a.cpp
|
||
# ? 任意1个字符 a?.txt ab.txt a.txt, abc.txt
|
||
# [abc] 匹配集合中一个字符 file[12].txt file1.txt file3.txt
|
||
# [a-z] 匹配范围内一个字符 file[a-z].txt filea.txt fileA.txt
|
||
# [!abc] 不在集合中的一个字符 file[!0-9].txt filea.txt file1.txt
|
||
glob_files_by_name() {
|
||
if [ $# -lt 4 ]; then
|
||
return 1
|
||
fi
|
||
|
||
local ret_name="$1"
|
||
local include_path="$2"
|
||
local exclude_path="$3"
|
||
local name_pattern="$4"
|
||
|
||
local -n ret="$ret_name"
|
||
ret=()
|
||
|
||
[ -z "$include_path" ] && return 0
|
||
[ ! -e "$include_path" ] && return 0
|
||
|
||
local include_abs
|
||
local exclude_abs=""
|
||
|
||
include_abs=$(realpath "$include_path")
|
||
|
||
if [ -n "$exclude_path" ] && [ -e "$exclude_path" ]; then
|
||
exclude_abs=$(realpath "$exclude_path")
|
||
fi
|
||
|
||
if [ -f "$include_abs" ]; then
|
||
local base_name="${include_abs##*/}"
|
||
if [[ "$base_name" == $name_pattern ]]; then
|
||
ret+=("$include_abs")
|
||
fi
|
||
return 0
|
||
fi
|
||
|
||
while IFS= read -r item; do
|
||
ret+=("$item")
|
||
done < <(
|
||
if [ -n "$exclude_abs" ]; then
|
||
find "$include_abs" \
|
||
\( -path "$exclude_abs" -o -path "$exclude_abs/*" \) -prune -o \
|
||
-type f -name "$name_pattern" -print
|
||
else
|
||
find "$include_abs" -type f -name "$name_pattern" -print
|
||
fi
|
||
)
|
||
}
|
||
|
||
# 生成命令行脚本 给某些makefile使用
|
||
|
||
_generate_case_dispatch_script_begin() {
|
||
if [ $# -ne 1 ]; then
|
||
return 1
|
||
fi
|
||
|
||
local ret_name="$1"
|
||
local -n ret="$ret_name"
|
||
|
||
ret=""
|
||
ret+=$'#!/usr/bin/env bash\n'
|
||
ret+=$'set -euo pipefail\n'
|
||
ret+=$'\n'
|
||
ret+=$'case "${2:-${1:-}}" in\n'
|
||
}
|
||
|
||
_generate_case_dispatch_script_append_case() {
|
||
if [ $# -ne 3 ]; then
|
||
return 1
|
||
fi
|
||
|
||
local ret_name="$1"
|
||
local case_label="$2"
|
||
local case_value="$3"
|
||
|
||
if [ -z "$case_label" ] || [ -z "$case_value" ]; then
|
||
return 1
|
||
fi
|
||
|
||
local -n ret="$ret_name"
|
||
|
||
ret+="${case_label})"$'\n'
|
||
printf -v ret '%s printf '\''%%s'\\\\n\'' "%s"\n' "$ret" "$case_value"
|
||
ret+=$' ;;\n'
|
||
}
|
||
|
||
_generate_case_dispatch_script_end() {
|
||
if [ $# -ne 1 ]; then
|
||
return 1
|
||
fi
|
||
|
||
local ret_name="$1"
|
||
local -n ret="$ret_name"
|
||
|
||
ret+=$'*)\n'
|
||
ret+=$' echo "unsupported args: $*" >&2\n'
|
||
ret+=$' exit 1\n'
|
||
ret+=$' ;;\n'
|
||
ret+=$'esac\n'
|
||
ret+=$'exit 0\n'
|
||
}
|
||
|
||
generate_case_dispatch_script_string() {
|
||
if [ $# -lt 3 ]; then
|
||
return 1
|
||
fi
|
||
|
||
local ret_name="$1"
|
||
shift
|
||
|
||
if [ -z "$ret_name" ]; then
|
||
return 1
|
||
fi
|
||
|
||
if [ $(( $# % 2 )) -ne 0 ]; then
|
||
return 1
|
||
fi
|
||
|
||
_generate_case_dispatch_script_begin "$ret_name" || return 1
|
||
|
||
local case_label=""
|
||
local case_value=""
|
||
|
||
while [ $# -gt 0 ]; do
|
||
case_label="$1"
|
||
case_value="$2"
|
||
shift 2
|
||
_generate_case_dispatch_script_append_case "$ret_name" "$case_label" "$case_value" || return 1
|
||
done
|
||
|
||
_generate_case_dispatch_script_end "$ret_name" || return 1
|
||
return 0
|
||
}
|
||
|
||
|
||
|
||
return 0 |