bash - 最近 24 小时从 HDFS 中的多个目录复制文件到本地

标签 bash hadoop hdfs

我在从 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”开头),然后输入从之前 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) }}'

但是这个正在复制比我早几天的文件,并且它只从一个目录(在本例中为 report1)复制文件。

有什么方法可以使它更灵活和正确。如果这可以用 bash 求解,而不是用 Python,那就太好了。 欢迎任何建议或链接到具有类似问题的好答案。

此外,不必处于某个循环中。我可以为每个报告使用单独的代码行。

最佳答案

注意:我无法对此进行测试,但您可以通过查看输出来逐步测试:

通常我会说Never parse the output of ls ,但是对于 Hadoop,您在这里别无选择,因为没有与 find 等效的方法。 (从2.7.0开始有找到,但是根据documentation非常有限)

第 1 步: 递归 ls

$ hadoop fs -ls -R /path/to/folder/

第 2 步:使用 仅选择文件和 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)'

第四步:一个一个复制文件:

首先,检查您要执行的命令:

$ 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)

关于bash - 最近 24 小时从 HDFS 中的多个目录复制文件到本地,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55364275/

相关文章:

linux - 结合 HBase 和 HDFS 导致 makeDirOnFileSystem 异常

bash - 在 bash 脚本中使用 bc

java - 如何解析 xml 元素节点 susing pig 脚本?

java - 此操作中有1个数据节点正在运行,并且1个节点未包括在内。 (伪分布式模式)

mongodb - MongoDB Hadoop PIG脚本引发 “Undefined Parameter :gte”异常

hadoop - 如何在 hadoop yarn 上获取应用程序运行时

java - 从 Java 代码运行 Linux Hadoop fs 命令

bash - 将多个不同的数组传递给 shell 函数

python - 如何根据多个条件提取子串?

bash - 为什么我的脚本的输出是 "mv: command not found"而当我直接在 shell 上运行它时却不是?