如何修改HDFS文件的最后修改时间?寻求UNIX touch等效方案
确实,HDFS的touchz命令和Unix的touch功能差异挺大的——它只能创建空文件或者更新现有文件的访问/修改时间到当前时间,完全不支持-d参数指定自定义时间。不过有几种靠谱的方法能实现你的需求,我给你整理一下:
方法一:用DistCp复制并保留时间戳
这是最容易上手的命令行方案,利用DistCp的属性保留功能同步时间戳:
- 先在本地创建一个临时文件,并用Unix
touch设置好你想要的时间:touch -d 20120101 /tmp/temp_timestamp_file - 用DistCp把这个本地文件复制到HDFS,覆盖目标文件,同时保留时间戳属性:
hadoop distcp -update -preserve t /tmp/temp_timestamp_file hdfs:///your/hdfs/file/path-update:只更新目标路径中已存在的文件,避免误操作其他文件-preserve t:明确指定保留时间戳(默认-preserve会保留权限、时间戳等属性,加t更精准)
这个方法的好处是不用写代码,适合快速修改单个或少量文件。如果目标文件很大,复制会花点时间,毕竟是全量复制,小文件的话完全没问题。
方法二:用Hadoop API直接修改
如果需要批量修改或者不想复制文件,用Hadoop的FileSystem API是更高效的方式。这里给个Java示例(也可以用Python的pyhdfs、hdfs3等库实现类似逻辑):
- 写一个简单的Java程序,调用
setTimes方法修改文件的修改时间:import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; public class HdfsTimestampChanger { public static void main(String[] args) throws Exception { if (args.length != 2) { System.err.println("Usage: HdfsTimestampChanger <hdfs-file-path> <new-timestamp-ms>"); System.exit(1); } Configuration conf = new Configuration(); FileSystem fs = FileSystem.get(conf); Path targetPath = new Path(args[0]); long newModTime = Long.parseLong(args[1]); // setTimes参数:文件路径,新修改时间(毫秒),新访问时间(-1表示不修改) boolean success = fs.setTimes(targetPath, newModTime, -1); if (success) { System.out.println("Successfully updated modification time for " + targetPath); } else { System.err.println("Failed to update modification time"); } fs.close(); } } - 编译并运行这个程序,需要先把Hadoop的依赖包加到classpath里。另外,你需要把目标时间转换成毫秒级时间戳,比如要设置为2012-01-01 00:00:00,可以用Unix命令生成:
得到的date -d "20120101" +%s | awk '{print $1 * 1000}'1325376000000就是对应的毫秒时间戳,然后运行程序:hadoop jar your-jar-file.jar HdfsTimestampChanger /hdfs/path/to/file 1325376000000
这个方法直接修改HDFS元数据,不用复制文件,效率很高,适合批量处理大量文件。
补充说明
- 如果你用的是Hadoop 3.x及以上版本,也可以检查一下
hdfs dfs -setfattr命令,但目前这个命令主要用于设置扩展属性,没法直接修改文件的默认修改时间,所以还是上面两种方法更靠谱。 - 不管用哪种方法,都需要确保你有目标文件的写权限,不然会报错。
内容的提问来源于stack exchange,提问作者Chakraborty
相关产品推荐
相关产品推荐

