bash—在过去24小时内将文件从hdfs中的多个目录复制到本地

ego6inou  于 2021-05-27  发布在  Hadoop
关注(0)|答案(2)|浏览(288)

我在将数据从hdfs传输到本地时遇到了问题。例如,我有:

/path/to/folder/report1/report1_2019_03_24-03_10*.csv
/path/to/folder/report1/report1_2019_03_24-04_12*.csv
...
/path/to/folder/report1/report1_2019_03_25-05_12*.csv
/path/to/folder/report1/report1_2019_03_25-06_12*.csv
/path/to/folder/report1/report1_2019_03_25-07_11*.csv
/path/to/folder/report1/report1_2019_03_25-08_13*.csv
/path/to/folder/report2/report2_out_2019_03_25-05_12*.csv
/path/to/folder/report2/report2_out_2019_03_25-06_11*.csv
/path/to/folder/report3/report3_TH_2019_03_25-05_12*.csv

所以我需要输入每个文件夹(report1,report2,report3。。。但并不是所有的文件都以“report”开头,然后是csv文件,这些文件是从以前的24小时拷贝到本地的,应该在每天早上4点完成(我可以用crontab安排)。问题是我不知道如何遍历文件并将时间戳作为参数传递。
我尝试过这样的东西(在堆栈溢出上找到)

/datalake/hadoop/bin/hadoop fs -ls /path/to/folder/report1/report1/*    |   tr -s " "    |    cut -d' ' -f6-8    |     grep "^[0-9]"    |    awk 'BEGIN{ MIN=1440; LAST=60*MIN; "date +%s" | getline NOW } { cmd="date -d'\''"$1" "$2"'\'' +%s"; cmd | getline WHEN; DIFF=NOW-WHEN; if(NOW > DIFF){ print "Migrating: "$3; system("datalake/hadoop/bin/hadoop fs -copyToLocal /path/to/local_dir/"$3) }}'

但是这一个复制的文件比我早几天,它只复制一个目录中的文件(在本例中是report1)。
有没有办法让这个更灵活、更正确。如果可以用bash而不是python来解决这个问题,那就太好了。欢迎任何建议或链接到一个类似问题的好答案。
而且,也不一定要在某个循环中。我可以为每个报表使用单独的代码行。

8iwquhpp

8iwquhpp1#

注意:我无法对此进行测试,但您可以通过查看输出一步一步地进行测试:
通常我会说从不解析 ls ,但是使用hadoop,您没有选择余地,因为这里没有与hadoop等价的工具 find . (因为2.7.0有一个发现,但根据文档,它非常有限)
步骤1:递归 ls ```
$ hadoop fs -ls -R /path/to/folder/

第2步:使用awk只选择文件和csv文件
目录由其以开头的权限来识别 `d` ,所以我们必须排除这些。最后一个以“csv”结尾的字段将识别csv文件:

$ hadoop fs -ls -R /path/to/folder/ | awk '!/^d/ && /.csv$/'

确保你没有在这里结束有趣的行是空的或只是目录名。。。
第三步:继续使用 `awk` 处理时间。我假设你有任何标准的awk,所以我不会使用gnu扩展。hadoop将时间格式输出为 `yyyy-MM-dd HH:mm` . 此格式可以排序,位于字段6和7中:

$ hadoop fs -ls -R /path/to/folder/
| awk -v cutoff="$(date -d '-24 hours' '+%F %H:%M')"
'(!/^d/) && /.csv$/ && (($6" "$7) > cutoff)'

步骤4:逐个复制文件:
首先,检查要执行的命令:

$ hadoop fs -ls -R /path/to/folder/
| awk -v cutoff="$(date -d '-24 hours' '+%F %H:%M')"
'(!/^d/) && /.csv$/ && (($6" "$7) > cutoff) {
print "migrating", $NF
cmd="hadoop fs -get "$NF" /path/to/local/"
print cmd
# system(cmd)
}'

(删除 `#` 如果你想执行)
或者

$ hadoop fs -ls -R /path/to/folder/
| awk -v cutoff="$(date -d '-24 hours' '+%F %H:%M')"
'(!/^d/) && /.csv$/ && (($6" "$7) > cutoff) {
print $NF
}' | xargs -I{} echo hadoop fs -get '{}' /path/to/local/

(删除 `echo` 如果你想执行)
vaj7vani

vaj7vani2#

您可以将“find”与“cp”结合使用,使其更简单,例如:

find /path/to/directory/ -type f -name "*.csv" | xargs cp -t /path/to/copy

如果要清除超过24小时的文件目录,可以使用:

find /path/to/files/ -type f -name "*.csv" -mtime +1 | xargs rm -f

也许您可以将它们实现为脚本,然后将其设置为cron上的任务。

相关问题