文件查找脚本#

脚本说明#

文件查找脚本用于根据多种条件查找文件,包括文件名、大小、修改时间、文件类型等,并支持多种输出格式。

脚本代码#

#!/bin/bash

# 文件查找脚本
# 功能:根据多种条件查找文件
# 作者:System Admin
# 日期:2026-01-01

set -euo pipefail

# 配置变量
SEARCH_PATH="."
OUTPUT_FORMAT="list"
MAX_RESULTS=0
CASE_SENSITIVE=false
VERBOSE=false

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m'

# 日志函数
log() {
    local level=$1
    shift
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo "[$timestamp] [$level] $@"
}

log_info() {
    log "INFO" "$@"
}

log_error() {
    log "ERROR" "$@"
}

# 按文件名查找
find_by_name() {
    local name_pattern=$1
    local path=${2:-.}
    
    log_info "按文件名查找: $name_pattern"
    
    if [ "$CASE_SENSITIVE" = true ]; then
        find "$path" -name "$name_pattern"
    else
        find "$path" -iname "$name_pattern"
    fi
}

# 按文件类型查找
find_by_type() {
    local file_type=$1
    local path=${2:-.}
    
    log_info "按文件类型查找: $file_type"
    
    case $file_type in
        file)
            find "$path" -type f
            ;;
        dir)
            find "$path" -type d
            ;;
        link)
            find "$path" -type l
            ;;
        *)
            log_error "无效的文件类型: $file_type"
            return 1
            ;;
    esac
}

# 按文件大小查找
find_by_size() {
    local size_condition=$1
    local path=${2:-.}
    
    log_info "按文件大小查找: $size_condition"
    
    find "$path" -type f -size "$size_condition"
}

# 按修改时间查找
find_by_mtime() {
    local time_condition=$1
    local path=${2:-.}
    
    log_info "按修改时间查找: $time_condition"
    
    find "$path" -type f -mtime "$time_condition"
}

# 按文件内容查找
find_by_content() {
    local content_pattern=$1
    local path=${2:-.}
    
    log_info "按文件内容查找: $content_pattern"
    
    if [ "$CASE_SENSITIVE" = true ]; then
        grep -r "$content_pattern" "$path" --include="*" -l
    else
        grep -ri "$content_pattern" "$path" --include="*" -l
    fi
}

# 按权限查找
find_by_permission() {
    local permission=$1
    local path=${2:-.}
    
    log_info "按权限查找: $permission"
    
    find "$path" -perm "$permission"
}

# 按所有者查找
find_by_owner() {
    local owner=$1
    local path=${2:-.}
    
    log_info "按所有者查找: $owner"
    
    find "$path" -user "$owner"
}

# 按组查找
find_by_group() {
    local group=$1
    local path=${2:-.}
    
    log_info "按组查找: $group"
    
    find "$path" -group "$group"
}

# 查找空文件
find_empty() {
    local path=${1:-.}
    
    log_info "查找空文件"
    
    find "$path" -type f -empty
}

# 查找大文件
find_large_files() {
    local size_threshold=${1:-100M}
    local path=${2:-.}
    
    log_info "查找大文件 (> $size_threshold)"
    
    find "$path" -type f -size "+$size_threshold" -exec ls -lh {} \;
}

# 查找重复文件
find_duplicates() {
    local path=${1:-.}
    
    log_info "查找重复文件"
    
    find "$path" -type f -exec md5sum {} \; | \
        sort | uniq -d -w 32 | \
        cut -d' ' -f3-
}

# 格式化输出
format_output() {
    local format=$1
    local files=($2)
    
    case $format in
        list)
            for file in "${files[@]}"; do
                echo "$file"
            done
            ;;
        detailed)
            for file in "${files[@]}"; do
                ls -lh "$file"
            done
            ;;
        table)
            printf "%-50s %-10s %-10s %-20s\n" "文件名" "大小" "权限" "修改时间"
            printf "%-50s %-10s %-10s %-20s\n" "$(printf '%.50s' "$(echo "----------" | tr '-' ' '))" "----------" "----------" "--------------------"
            
            for file in "${files[@]}"; do
                local size=$(ls -lh "$file" | awk '{print $5}')
                local perms=$(ls -ld "$file" | awk '{print $1}')
                local mtime=$(ls -ld "$file" | awk '{print $6, $7, $8}')
                printf "%-50s %-10s %-10s %-20s\n" "$file" "$size" "$perms" "$mtime"
            done
            ;;
        json)
            echo "["
            local first=true
            for file in "${files[@]}"; do
                if [ "$first" = false ]; then
                    echo ","
                fi
                first=false
                
                local size=$(stat -c %s "$file")
                local perms=$(stat -c %a "$file")
                local mtime=$(stat -c %Y "$file")
                
                printf "  {"
                printf "\"name\": \"%s\", " "$file"
                printf "\"size\": %d, " "$size"
                printf "\"permissions\": \"%s\", " "$perms"
                printf "\"mtime\": %d" "$mtime"
                printf "}"
            done
            echo ""
            echo "]"
            ;;
        *)
            log_error "无效的输出格式: $format"
            return 1
            ;;
    esac
}

# 复合查找
complex_find() {
    local path=$1
    shift
    
    log_info "执行复合查找"
    
    local find_cmd="find \"$path\""
    
    while [ $# -gt 0 ]; do
        case $1 in
            -name)
                find_cmd="$find_cmd -name \"$2\""
                shift 2
                ;;
            -type)
                find_cmd="$find_cmd -type \"$2\""
                shift 2
                ;;
            -size)
                find_cmd="$find_cmd -size \"$2\""
                shift 2
                ;;
            -mtime)
                find_cmd="$find_cmd -mtime \"$2\""
                shift 2
                ;;
            -perm)
                find_cmd="$find_cmd -perm \"$2\""
                shift 2
                ;;
            -user)
                find_cmd="$find_cmd -user \"$2\""
                shift 2
                ;;
            -group)
                find_cmd="$find_cmd -group \"$2\""
                shift 2
                ;;
            *)
                log_error "无效的选项: $1"
                return 1
                ;;
        esac
    done
    
    eval "$find_cmd"
}

# 显示帮助
show_help() {
    echo "用法: $0 [选项] <查找模式> [参数]"
    echo ""
    echo "选项:"
    echo "  -p <路径>        搜索路径(默认: .)"
    echo "  -f <格式>        输出格式(list/detailed/table/json)"
    echo "  -m <数量>        最大结果数量(0=无限制)"
    echo "  -c               区分大小写"
    echo "  -v               详细输出"
    echo "  -h               显示帮助信息"
    echo ""
    echo "查找模式:"
    echo "  name <模式>              按文件名查找"
    echo "  type <类型>              按文件类型查找(file/dir/link)"
    echo "  size <条件>              按文件大小查找(如: +100M, -1K)"
    echo "  mtime <条件>             按修改时间查找(如: -7, +30)"
    echo "  content <模式>           按文件内容查找"
    echo "  perm <权限>              按权限查找(如: 755)"
    echo "  owner <用户>             按所有者查找"
    echo "  group <组>               按组查找"
    echo "  empty                    查找空文件"
    echo "  large [大小]             查找大文件(默认: 100M)"
    echo "  duplicates               查找重复文件"
    echo "  complex <选项>...        复合查找"
    echo ""
    echo "示例:"
    echo "  $0 name \"*.txt\""
    echo "  $0 type file"
    echo "  $0 size \"+100M\""
    echo "  $0 mtime \"-7\""
    echo "  $0 content \"error\""
    echo "  $0 perm 755"
    echo "  $0 large"
    echo "  $0 duplicates"
    echo "  $0 complex -name \"*.log\" -mtime -7 -size +1M"
}

# 主函数
main() {
    # 解析选项
    while getopts "p:f:m:cvh" opt; do
        case $opt in
            p)
                SEARCH_PATH="$OPTARG"
                log_info "搜索路径: $SEARCH_PATH"
                ;;
            f)
                OUTPUT_FORMAT="$OPTARG"
                log_info "输出格式: $OUTPUT_FORMAT"
                ;;
            m)
                MAX_RESULTS="$OPTARG"
                log_info "最大结果: $MAX_RESULTS"
                ;;
            c)
                CASE_SENSITIVE=true
                log_info "区分大小写"
                ;;
            v)
                VERBOSE=true
                log_info "详细输出"
                ;;
            h)
                show_help
                exit 0
                ;;
            *)
                log_error "无效选项: $opt"
                show_help
                exit 1
                ;;
        esac
    done
    
    shift $((OPTIND - 1))
    
    # 检查参数
    if [ $# -eq 0 ]; then
        log_error "缺少查找模式"
        show_help
        exit 1
    fi
    
    # 检查搜索路径
    if [ ! -d "$SEARCH_PATH" ]; then
        log_error "搜索路径不存在: $SEARCH_PATH"
        exit 1
    fi
    
    MODE=$1
    shift
    
    # 执行查找
    local results=()
    case $MODE in
        name)
            if [ $# -eq 0 ]; then
                log_error "缺少文件名模式"
                exit 1
            fi
            mapfile -t results < <(find_by_name "$1" "$SEARCH_PATH")
            ;;
        type)
            if [ $# -eq 0 ]; then
                log_error "缺少文件类型"
                exit 1
            fi
            mapfile -t results < <(find_by_type "$1" "$SEARCH_PATH")
            ;;
        size)
            if [ $# -eq 0 ]; then
                log_error "缺少大小条件"
                exit 1
            fi
            mapfile -t results < <(find_by_size "$1" "$SEARCH_PATH")
            ;;
        mtime)
            if [ $# -eq 0 ]; then
                log_error "缺少时间条件"
                exit 1
            fi
            mapfile -t results < <(find_by_mtime "$1" "$SEARCH_PATH")
            ;;
        content)
            if [ $# -eq 0 ]; then
                log_error "缺少内容模式"
                exit 1
            fi
            mapfile -t results < <(find_by_content "$1" "$SEARCH_PATH")
            ;;
        perm)
            if [ $# -eq 0 ]; then
                log_error "缺少权限"
                exit 1
            fi
            mapfile -t results < <(find_by_permission "$1" "$SEARCH_PATH")
            ;;
        owner)
            if [ $# -eq 0 ]; then
                log_error "缺少用户名"
                exit 1
            fi
            mapfile -t results < <(find_by_owner "$1" "$SEARCH_PATH")
            ;;
        group)
            if [ $# -eq 0 ]; then
                log_error "缺少组名"
                exit 1
            fi
            mapfile -t results < <(find_by_group "$1" "$SEARCH_PATH")
            ;;
        empty)
            mapfile -t results < <(find_empty "$SEARCH_PATH")
            ;;
        large)
            local size=${1:-100M}
            mapfile -t results < <(find_large_files "$size" "$SEARCH_PATH")
            ;;
        duplicates)
            mapfile -t results < <(find_duplicates "$SEARCH_PATH")
            ;;
        complex)
            mapfile -t results < <(complex_find "$SEARCH_PATH" "$@")
            ;;
        *)
            log_error "无效的查找模式: $MODE"
            show_help
            exit 1
            ;;
    esac
    
    # 限制结果数量
    if [ $MAX_RESULTS -gt 0 ] && [ ${#results[@]} -gt $MAX_RESULTS ]; then
        log_info "限制结果数量: ${MAX_RESULTS}"
        results=("${results[@]:0:$MAX_RESULTS}")
    fi
    
    # 输出结果
    log_info "找到 ${#results[@]} 个结果"
    format_output "$OUTPUT_FORMAT" "${results[@]}"
}

# 执行主函数
main "$@"

使用说明#

  1. 添加执行权限:

    chmod +x file_finder.sh
  2. 基本用法:

    # 按文件名查找
    ./file_finder.sh name "*.txt"
    
    # 按文件类型查找
    ./file_finder.sh type file
    
    # 按文件大小查找
    ./file_finder.sh size "+100M"
    
    # 按修改时间查找
    ./file_finder.sh mtime "-7"
    
    # 按文件内容查找
    ./file_finder.sh content "error"
    
    # 查找大文件
    ./file_finder.sh large
  3. 高级选项:

    # 指定搜索路径
    ./file_finder.sh -p /var/log name "*.log"
    
    # 使用详细输出格式
    ./file_finder.sh -f detailed name "*.txt"
    
    # 限制结果数量
    ./file_finder.sh -m 10 type file
    
    # 区分大小写
    ./file_finder.sh -c name "File.txt"
    
    # 复合查找
    ./file_finder.sh complex -name "*.log" -mtime -7 -size +1M

功能特点#

  • 支持多种查找条件
  • 文件名、类型、大小、时间等
  • 文件内容搜索
  • 权限和所有者查找
  • 复合条件查找
  • 多种输出格式
  • 结果数量限制
  • 大小写敏感选项

依赖项#

  • find: 用于文件查找
  • grep: 用于内容搜索
  • md5sum: 用于查找重复文件

注意事项#

  1. 文件内容搜索可能较慢
  2. 查找大目录时注意性能
  3. JSON格式输出需要正确处理
  4. 复合查找时注意条件顺序
  5. 权限查找需要相应权限