介绍
零售商现在收到了来自两家门店、分属两个日期的文件。计数程序会处理你提供的文件;它无法猜测你想处理哪一天,也无法识别应当排除的旧结果文件。因此,输入选择错误时,即使程序正确,也可能得到错误的业务答案。
你已学会保留、复制、归档和导出单个文件。这里将从单个文件推进到批次输入,即有意选择的一组文件。你将把不同日期分开,比较文件数量和内容,并保存一份清单(manifest):列出一次运行所选的确切 HDFS 文件。
HDFS 存储文件内容,并不理解零售数据的列、日期或 CSV 表头。组织输入之前,你将先观察这一职责边界。本实验独立准备了本地文件和一份先前结果的示例,不依赖之前实验的状态。请使用终端完成操作。
区分存储的文本与文本含义
在这一步中,你将查看本地收到的文件,并观察上传 CSV 后,表头仍会作为普通文本保留。
先进入本地工作目录:
cd /home/labex/project
列出第一个日期收到的文件。用日期作为目录名是一种实用约定,并不是 HDFS 强制实施的数据类型:
ls /home/labex/project/data/2026-10-14
你应该看到 store-east.txt 和 store-west.txt。使用本地 cat,按此顺序读取它们:
cat /home/labex/project/data/2026-10-14/store-east.txt /home/labex/project/data/2026-10-14/store-west.txt
预期文本如下:
notebook pen
notebook
folder pen
这里每个单词都是记录的商品标签。这些文件适用于后续将学习的词频统计流程。另一个系统提供了不同格式的数据。读取这份小型 CSV 预览文件:
cat /home/labex/project/data/orders-preview.csv
预期文本如下:
product,quantity
notebook,2
pen,1
CSV 使用逗号分隔字段。第一行是命名各列的表头(header),其余两行是业务记录。HDFS 不会自动删除第一行,也不会把 quantity 解释为整数。
将这份预览文件与商品标签批次分开保存。为它创建一个 HDFS 目录:
hdfs dfs -mkdir -p /user/labex/batch-inputs/preview
上传 CSV:
hdfs dfs -put /home/labex/project/data/orders-preview.csv /user/labex/batch-inputs/preview/orders.csv
读回文件:
hdfs dfs -cat /user/labex/batch-inputs/preview/orders.csv
包括表头在内的三行都被保留了。是否跳过表头、是否解析数字,属于处理阶段的决策。即使每个文件都能读取,把这份文件混入单词标签输入,也会改变计算的含义。
按日期组织收到的文件
在这一步中,你将为每个日期建立独立的原始输入目录,并上传对应的两份门店文件。
使用能清楚区分输入与输出的目录布局:
batch-inputs/
raw/2026-10-14/ 第一天的商品文件
raw/2026-10-15/ 下一天的商品文件
preview/ CSV 格式示例
results/previous-run/ 预置的先前运行输出
先前结果只是用于学习输入选择的实验数据,不能成为新原始批次的一部分。创建这两个每日目录:
hdfs dfs -mkdir -p /user/labex/batch-inputs/raw/2026-10-14 /user/labex/batch-inputs/raw/2026-10-15
Shell 的 *.txt 模式匹配以 .txt 结尾的本地文件名。在下一条命令中,Shell 会在运行 HDFS 客户端之前,将未加引号的本地模式展开为两个源路径。最后一个参数是已存在的 HDFS 目录:
hdfs dfs -put /home/labex/project/data/2026-10-14/*.txt /user/labex/batch-inputs/raw/2026-10-14/
现在只修改源和目标两处的日期,上传第二天收到的文件:
hdfs dfs -put /home/labex/project/data/2026-10-15/*.txt /user/labex/batch-inputs/raw/2026-10-15/
如果目标文件已经存在,请先检查,再决定是否覆盖。保留原始输入,比仅仅为了重新执行上传命令而删除它更有价值。
使用文件生命周期实验中学过的 -count 检查每个批次:
hdfs dfs -count /user/labex/batch-inputs/raw/2026-10-14 /user/labex/batch-inputs/raw/2026-10-15
每个日期应该包含一个目录和两个文件。内容大小列不必一致,因为两个日期包含不同记录。仅凭文件数量无法证明选择了正确日期,因此还要列出第一个日期:
hdfs dfs -ls /user/labex/batch-inputs/raw/2026-10-14
两个条目都应该位于 2026-10-14 下,并显示预期的门店文件名。这里只用几个小文件,便于阅读练习。在大得多的规模下,大量微小文件会给 HDFS 带来元数据开销;但这并不意味着每个小文件都必须合并。
选择并核对一个批次
在这一步中,你将为 10 月 14 日准备准确的文件清单,并将输入文本与预期的本地文件进行比较。
运行命令之前,先预测清单应该包含哪个目录:整个 batch-inputs 目录树、整个 raw 目录树,还是仅包含 raw/2026-10-14?范围更明确的日期目录与目标日期一致,并排除了下一天、CSV 预览和旧结果。
HDFS 的 -ls -C 选项只打印路径,不显示详细列表中的其他列。对所选日期使用它:
hdfs dfs -ls -C /user/labex/batch-inputs/raw/2026-10-14
两个路径应该分别以 store-east.txt 和 store-west.txt 结尾。为了让保存的清单更容易比较,可以使用写作 | 的 Shell 管道(pipeline),将第一条命令的输出传给第二条命令。sort 对行排序,> 将结果保存到本地:
hdfs dfs -ls -C /user/labex/batch-inputs/raw/2026-10-14 | sort > /home/labex/project/output/input-manifest.txt
读取清单:
cat /home/labex/project/output/input-manifest.txt
预期路径如下:
/user/labex/batch-inputs/raw/2026-10-14/store-east.txt
/user/labex/batch-inputs/raw/2026-10-14/store-west.txt
你也可以在 HDFS 端使用模式。单引号保留 *.txt,让 HDFS 客户端匹配远程路径,而不是由本地 Shell 匹配:
hdfs dfs -cat '/user/labex/batch-inputs/raw/2026-10-14/*.txt' > /home/labex/project/output/selected-input.txt
对于这些文件名,HDFS 会先读取 east 文件,再读取 west 文件。按同样的明确顺序保存对应的本地文本:
cat /home/labex/project/data/2026-10-14/store-east.txt /home/labex/project/data/2026-10-14/store-west.txt > /home/labex/project/output/expected-input.txt
比较两份文件:
diff /home/labex/project/output/expected-input.txt /home/labex/project/output/selected-input.txt
应该没有差异输出。还可以用 wc -l 进行另一项检查,它统计每个文件中以换行符结尾的行数:
wc -l /home/labex/project/output/selected-input.txt
结果应该以 3 开头。这是包含五个商品标签的三行文本,并不是三个订单。记录的含义由文件格式和任务决定,不由 HDFS 决定。文件清单、内容和行数共同明确了你选择的输入。
总结
你将 CSV 预览与纯文本商品标签文件分开,把每个日期的原始输入保存在独立目录中,并使用清单选择了一个批次。你同时核对了文件名和内容,没有仅凭上传成功或文件数量就认定输入正确。
在下一个挑战中,你将使用已经练习过的文件管理和输入选择技能,组织新收到的数据。



