从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
Run Code Online (Sandbox Code Playgroud)
因此,我需要输入每个文件夹(report1,report2,report3 ...,但并非所有文件夹都以“ report”开头),然后输入从先前24小时复制到本地的CSV文件,并且应该每天早晨4点完成是(我可以使用crontab安排它)。问题是我不知道如何遍历文件并将时间戳记作为参数传递。
我已经尝试过类似的东西(在Stack Overflow上找到)
/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) }}'
Run Code Online (Sandbox Code Playgroud)
但这是复制比我早几天的文件,并且仅从一个目录(在本例中为report1)复制文件。
有什么方法可以使此操作更加灵活和正确。如果可以使用bash而不是Python来解决问题,那就太好了。任何建议都欢迎或链接到具有类似问题的良好答案。
另外,也不必处于某个循环中。我可以为每个报告使用分隔的代码行。
注意:我无法对此进行测试,但是您可以通过查看输出来逐步测试此:
通常,我会说“ 永不解析”的输出ls,但是使用Hadoop时,您没有选择余地,因为没有等效项find。(从2.7.0版本开始可以找到,但是根据文档,它非常有限)
步骤1:递归ls
$ hadoop fs -ls -R /path/to/folder/
Run Code Online (Sandbox Code Playgroud)
第2步:使用awk仅选择文件,仅CSV文件的
目录可以通过以开头的权限来识别d,因此我们必须排除它们。CSV文件由最后一个以“ csv”结尾的字段识别:
$ hadoop fs -ls -R /path/to/folder/ | awk '!/^d/ && /\.csv$/'
Run Code Online (Sandbox Code Playgroud)
确保您在此处不会出现有趣的行,这些行是空的或只是目录名...
步骤3:继续使用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)'
Run Code Online (Sandbox Code Playgroud)
步骤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)
}'
Run Code Online (Sandbox Code Playgroud)
(#如果要执行,请删除)
要么
$ 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/
Run Code Online (Sandbox Code Playgroud)
(echo如果要执行,请删除)