hdfs dfs -put 报 No such file or directory 的排查与解决
1 问题背景
实训数据预处理后得到 20 个 csv 文件,需要上传到 HDFS 的 /edu/raw 目录,供后续 Spark 清洗使用。其中 7 个访问日志文件来自平台导出,原始文件名形如 data (2).csv、data (3).csv,名称中含有空格和括号。
2 问题现象
在 hadoop01 上执行上传命令后,出现两类报错:
现象一:7 个日志文件(data (2).csv 至 data (9).csv)报 No such file or directory,提示 /home/hadoop/data/csv/data (2).csv 不存在。
现象二:13 个已上传成功的文件再次执行时报 File exists,提示目标文件已存在。
矛盾之处在于:FinalShell 的文件管理器中可以看到这 7 个文件明明位于 /home/hadoop/data/csv 目录下,与报错提示相矛盾。
3 排查过程
3.1 确认文件真实存在
先在 FinalShell 文件管理器导航到 /home/hadoop/data/csv,确认 20 个 csv 文件均在目录中,排除漏传的可能。
3.2 用 shell 视角确认文件名
在终端执行 ls 命令查看目录内容:
ls -la ~/data/csv/
输出显示 20 个文件全部存在,data (2).csv 等文件名显示正常,权限与属主正确。
3.3 排除隐藏字符
用循环逐一打印文件名,检查是否存在不可见字符或全角字符差异:
cd ~/data/csv && for f in data*; do echo "[$f]"; done
输出为 data (2).csv 等正常名称,排除文件名编码异常。
3.4 定位根因
本地文件与文件名均正常,但 hdfs dfs -put 仍报文件不存在,说明问题出在 Hadoop 的 FsShell 命令层:它对待空格、括号等特殊字符的文件名解析不友好,将 data (2).csv 误判为不存在。
4 解决方案
4.1 方案一:重命名后上传(推荐)
将带空格和括号的 7 个日志文件统一重命名为简洁的 log_n.csv,既解决上传问题,也避免后续 Spark 读取 HDFS 路径时再次踩坑:
cd ~/data/csv
for n in 2 3 4 5 6 8 9; do mv "data ($n).csv" "log_$n.csv"; done
重命名对照如下:
表1 文件名重命名对照
|--------------|-----------|
| 原文件名 | 新文件名 |
| data (2).csv | log_2.csv |
| data (3).csv | log_3.csv |
| data (4).csv | log_4.csv |
| data (5).csv | log_5.csv |
| data (6).csv | log_6.csv |
| data (8).csv | log_8.csv |
| data (9).csv | log_9.csv |
只补传这 7 个新文件(其余 13 个已在 HDFS,无需重复上传):
hdfs dfs -put ~/data/csv/log_*.csv /edu/raw/
4.2 方案二:逐个带引号上传(备选)
若不想改文件名,可对每个文件加引号后逐个上传,避免通配符展开和特殊字符解析问题:
hdfs dfs -put "$HOME/data/csv/data (2).csv" /edu/raw/
该方案可行但繁琐,文件多时不推荐。
5 验证结果
执行目录查看命令确认上传结果:
hdfs dfs -ls /edu/raw
Found 20 items
HDFS 的 /edu/raw 目录下共 20 个文件:7 个 log_*.csv 日志文件加 13 个统计表文件,全部上传成功,数据准备阶段完成。
6 经验总结
上传到 HDFS 的文件名应避免空格、括号等特殊字符,命名尽量使用字母、数字和下划线,从源头规避解析问题。
要区分两类报错:No such file or directory 表示源路径无法读取或解析,需检查文件名与路径;File exists 表示目标已存在,重复上传时可用 -f 参数覆盖。
shell 通配符由 bash 展开后传入命令,文件名含空格时建议加引号或先重命名,避免命令层二次解析出错。
遇到管理工具显示正常但命令行报错的情况,先回到 shell 用 ls 确认,再考虑命令层对特殊字符的处理差异。