基础版 - 查找并删除
#!/bin/bash
# 基本删除所有无效软链接
find /path/to/search -type l ! -exec test -e {} \; -delete
# 带确认提示的版本
find /path/to/search -type l ! -exec test -e {} \; -print -delete
安全版 - 先预览再删除
#!/bin/bash
# 设置搜索路径
SEARCH_DIR="${1:-.}"
echo "正在扫描无效软链接..."
INVALID_LINKS=$(find "$SEARCH_DIR" -type l ! -exec test -e {} \; 2>/dev/null)
if [ -z "$INVALID_LINKS" ]; then
echo "未发现无效软链接"
exit 0
fi
echo "发现以下无效软链接:"
echo "-------------------"
echo "$INVALID_LINKS"
echo "-------------------"
read -p "是否删除这些无效链接? (y/n): " CONFIRM
if [[ $CONFIRM == [yY] ]]; then
echo "$INVALID_LINKS" | while read -r link; do
rm "$link" && echo "已删除: $link"
done
echo "清理完成!"
else
echo "已取消操作"
fi
带日志的版本
#!/bin/bash
# 配置
SEARCH_DIR="${1:-.}"
LOG_FILE="/var/log/clean_symlinks_$(date +%Y%m%d).log"
DRY_RUN=false
# 解析参数
while [[ $# -gt 0 ]]; do
case $1 in
--dry-run) DRY_RUN=true; shift ;;
--log=*) LOG_FILE="${1#*=}"; shift ;;
*) SEARCH_DIR="$1"; shift ;;
esac
done
echo "=================================" | tee -a "$LOG_FILE"
echo "清理无效软链接 - $(date)" | tee -a "$LOG_FILE"
echo "搜索目录: $SEARCH_DIR" | tee -a "$LOG_FILE"
echo "日志文件: $LOG_FILE" | tee -a "$LOG_FILE"
DELETED_COUNT=0
ERROR_COUNT=0
while IFS= read -r -d '' link; do
if [ ! -e "$link" ]; then
TARGET=$(readlink "$link")
if [ "$DRY_RUN" = true ]; then
echo "[DRY RUN] 将删除: $link -> $TARGET" | tee -a "$LOG_FILE"
else
if rm "$link" 2>/dev/null; then
echo "[DELETED] $link -> $TARGET" | tee -a "$LOG_FILE"
((DELETED_COUNT++))
else
echo "[ERROR] 无法删除: $link" | tee -a "$LOG_FILE"
((ERROR_COUNT++))
fi
fi
fi
done < <(find "$SEARCH_DIR" -type l -print0 2>/dev/null)
echo "=================================" | tee -a "$LOG_FILE"
echo "统计信息:" | tee -a "$LOG_FILE"
if [ "$DRY_RUN" = true ]; then
echo "模拟运行 - 将删除 $DELETED_COUNT 个链接" | tee -a "$LOG_FILE"
else
echo "已删除: $DELETED_COUNT" | tee -a "$LOG_FILE"
echo "失败: $ERROR_COUNT" | tee -a "$LOG_FILE"
fi
交互式选择版
#!/bin/bash
# 交互式选择要删除的链接
SEARCH_DIR="${1:-.}"
echo "扫描无效软链接..."
declare -a INVALID_LINKS=()
while IFS= read -r -d '' link; do
if [ ! -e "$link" ]; then
INVALID_LINKS+=("$link")
fi
done < <(find "$SEARCH_DIR" -type l -print0 2>/dev/null)
if [ ${#INVALID_LINKS[@]} -eq 0 ]; then
echo "未发现无效软链接"
exit 0
fi
echo "发现 ${#INVALID_LINKS[@]} 个无效软链接:"
echo "----------------------------------------"
for i in "${!INVALID_LINKS[@]}"; do
echo "[$((i+1))] ${INVALID_LINKS[$i]} -> $(readlink "${INVALID_LINKS[$i]}")"
done
echo "----------------------------------------"
echo "请选择操作:"
echo "a) 全部删除"
echo "s) 选择删除"
echo "q) 退出"
read -p "选择: " CHOICE
case $CHOICE in
a|A)
for link in "${INVALID_LINKS[@]}"; do
rm "$link" && echo "已删除: $link"
done
echo "全部删除完成"
;;
s|S)
read -p "输入要删除的编号(逗号分隔,如 1,3,5): " NUMBERS
IFS=',' read -ra SELECTED <<< "$NUMBERS"
for num in "${SELECTED[@]}"; do
index=$((num-1))
if [ $index -ge 0 ] && [ $index -lt ${#INVALID_LINKS[@]} ]; then
rm "${INVALID_LINKS[$index]}" && echo "已删除: ${INVALID_LINKS[$index]}"
else
echo "无效编号: $num"
fi
done
;;
q|Q)
echo "退出"
exit 0
;;
*)
echo "无效选择"
exit 1
;;
esac
归档无效链接(安全删除前)
#!/bin/bash
# 将无效链接移动到备份目录
SEARCH_DIR="${1:-.}"
BACKUP_DIR="./backup_symlinks_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$BACKUP_DIR"
COUNT=0
while IFS= read -r -d '' link; do
if [ ! -e "$link" ]; then
# 创建备份路径
REL_PATH="${link#./}"
BACKUP_PATH="$BACKUP_DIR/$REL_PATH"
mkdir -p "$(dirname "$BACKUP_PATH")"
# 保存链接信息
echo "原始路径: $link" > "${BACKUP_PATH}.info"
echo "目标路径: $(readlink "$link")" >> "${BACKUP_PATH}.info"
# 移动链接
mv "$link" "$BACKUP_PATH" 2>/dev/null && ((COUNT++))
fi
done < <(find "$SEARCH_DIR" -type l -print0 2>/dev/null)
echo "已归档 $COUNT 个无效链接到 $BACKUP_DIR"
echo "如需恢复,请使用 restore_backup.sh 脚本"
使用说明
- 基本使用:
# 直接运行 ./clean_symlinks.sh /path/to/search
在当前目录执行
./clean_symlinks.sh

2. **权限要求**:
```bash
# 添加执行权限
chmod +x clean_symlinks.sh
# 可能需要sudo权限
sudo ./clean_symlinks.sh /system/path
- 安全建议:
- 首次使用添加
--dry-run参数预览结果 - 建议先在测试目录验证
- 对系统目录操作时务必谨慎
这些脚本覆盖了从简单到复杂的各种需求,你可以根据实际情况选择使用。