You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Shell脚本查找非硬链接且不在硬链接目录下的文件

问题根源

原命令find /1 -type f -links 1 -print仅对文件自身的硬链接计数做校验,完全没有处理路径上父目录为重复inode的场景——这类场景不仅包括目录硬链接,也包括安卓系统中大量存在的绑定挂载(比如/data/data与/data/user/0就是典型的同inode绑定挂载路径)。同个文件会通过多个重复目录路径被扫描到,自然会出现重复输出。

实现逻辑

要满足需求只需要守住两个过滤规则:

  • 目标文件自身硬链接计数为1,即文件本身没有其他硬链接别名
  • 所有同唯一标识(设备号+inode号,避免跨文件系统inode重复)的目录、文件仅处理一次,从根源避免重复进入重复目录、重复输出同inode文件
可用脚本

安卓环境适配版(兼容POSIX shell、adb shell,无需bash依赖)

# 替换为实际要搜索的根路径
SEARCH_ROOT="/data"
# 临时文件存储已处理的「设备号:inode号」唯一标识
TMP_MARK=$(mktemp)
trap 'rm -f "$TMP_MARK"' EXIT

find "$SEARCH_ROOT" -exec stat -c '%d:%i %F %n' {} \; | while read -r unique_id ftype path; do
    # 该inode已处理过,直接跳过
    if grep -qxF "$unique_id" "$TMP_MARK"; then
        continue
    fi
    # 标记为已处理
    echo "$unique_id" >> "$TMP_MARK"
    # 仅输出普通文件、且硬链接数为1的条目
    if [ "$ftype" = "regular file" ] && [ ! -L "$path" ]; then
        link_cnt=$(stat -c '%h' "$path")
        if [ "$link_cnt" -eq 1 ]; then
            echo "$path"
        fi
    fi
done

普通Linux Bash版(性能更好)

#!/bin/bash
SEARCH_ROOT="/1"
declare -A seen
# 格式:设备号 inode 类型 路径
find "$SEARCH_ROOT" -printf '%D %i %y %p\n' | while read -r dev inode ftype path; do
    unique_id="${dev}:${inode}"
    if [[ -n "${seen[$unique_id]}" ]]; then
        continue
    fi
    seen[$unique_id]=1
    if [[ "$ftype" == "f" ]]; then
        link_cnt=$(stat -c '%h' "$path")
        if [[ "$link_cnt" -eq 1 ]]; then
            echo "$path"
        fi
    fi
done
效果说明
  • 遍历过程中首次遇到某个inode的目录/文件时就会做标记,后续再遇到同唯一标识的条目(不管是另一个路径的硬链接目录、绑定挂载目录,还是同个文件的其他硬链接路径)都会直接跳过,不会重复处理
  • 针对给出的安卓NFC目录示例,最终只会输出1次service_state.xml的路径,不会重复
  • 脚本默认输出先遍历到的路径,如果需要固定输出某个路径前缀下的结果,可以调整搜索根路径的顺序,把优先要输出的路径放在前面遍历

内容的提问来源于stack exchange,提问作者lucky1928

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 16:42:58