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

求助:Shell脚本遍历HDFS目录及获取文件创建时间失败问题

解决HDFS目录遍历与文件时间筛选的问题

你遇到的问题主要来自两个核心点:HDFS的ls输出格式和本地Linux完全不同,以及操作HDFS文件需要用专门的Hadoop命令而非本地命令,我来一步步帮你修正脚本:

为什么原来的遍历写法失效?

本地ls /path/*会直接输出每个文件的路径,但HDFS的hadoop fs -ls /TestDir输出是这样的格式:

Found 2 items
-rw-r--r--   3 user hadoop        123 2024-05-20 10:30 /TestDir/file1.txt
-rw-r--r--   3 user hadoop        456 2024-05-21 14:15 /TestDir/file2.txt

当你用for i in hadoop fs -ls /TestDir``时,shell会把所有空格分割的内容都当成循环项——比如-rw-r--r--、3、user、/TestDir/file1.txt都会被单独赋值给i,这显然不是你要的文件路径。

修正后的完整脚本

推荐用hadoop fs -find来遍历HDFS文件(更可靠,支持递归/非递归,还能处理带空格的文件名),同时替换本地命令为HDFS专用命令:

#!/bin/bash

# 配置路径
HDFS_SOURCE_DIR="/TestDir"
LOCAL_OUTPUT_DIR="/home/user/OutputDir"

# 遍历HDFS目录下的所有文件(-type f 表示只找文件,排除目录;如果要递归子目录去掉-maxdepth 1)
hadoop fs -find "$HDFS_SOURCE_DIR" -maxdepth 1 -type f | while read -r file_path; do
    echo "正在处理文件: $file_path"
    
    # 获取HDFS文件的时间(这里用%y取最后修改时间,若需创建时间请看下文注意事项)
    file_time=$(hadoop fs -stat %y "$file_path")
    # 提取日期部分(格式:YYYY-MM-DD)
    file_date=$(echo "$file_time" | cut -c 1-10)
    echo "文件日期: $file_date"
    
    # 和当前日期对比
    if [ "$file_date" = "$(date +%F)" ]; then
        # 从HDFS复制到本地(用copyToLocal或get命令,不能用本地cp)
        hadoop fs -copyToLocal "$file_path" "$LOCAL_OUTPUT_DIR/"
        echo "✅ 已成功复制 $file_path 到 $LOCAL_OUTPUT_DIR"
    fi
done

关键细节说明

  1. 遍历方式的选择

    • 如果不需要递归子目录,加-maxdepth 1参数;如果要递归遍历所有子目录,去掉这个参数即可。
    • 用while read -r替代for循环:如果文件名包含空格,for会按空格分割路径,而while read会按行读取,避免错误。
  2. HDFS文件时间的获取
    HDFS的stat命令参数和本地略有差异,你可以用hadoop fs -stat --help查看你当前版本支持的选项:

    • %y:文件最后修改时间(人类可读格式,如2024-05-20 10:30:00)
    • %Y:最后修改时间的毫秒时间戳
    • 部分Hadoop版本支持%b获取文件创建时间(birth time),如果你的需求是创建时间,把%y换成%b即可。
  3. HDFS文件操作命令
    本地的cp、stat等命令无法直接操作HDFS文件,必须用Hadoop提供的命令:

    • 复制HDFS文件到本地:hadoop fs -copyToLocal 或 hdfs dfs -get
    • 获取HDFS文件属性:hadoop fs -stat
    • 查看HDFS目录:hadoop fs -ls

备用方案(不用find,用ls处理)

如果你坚持用ls,需要过滤掉无用行并提取文件路径:

#!/bin/bash

HDFS_SOURCE_DIR="/TestDir"
LOCAL_OUTPUT_DIR="/home/user/OutputDir"

# 过滤掉ls开头的"Found X items"行,然后提取第8个字段(文件路径)
for file_path in $(hadoop fs -ls "$HDFS_SOURCE_DIR" | grep -v "^Found" | awk '{print $8}'); do
    # 后续逻辑和上面的脚本一致
    echo "正在处理文件: $file_path"
    # ... 省略时间获取和复制逻辑
done

⚠️ 注意:这种方式不支持带空格的文件名,优先推荐find+while read的写法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:51:12