output_path=s3://output
unziped_dir=s3://2019-01-03
files=`hadoop fs -ls $output_path/ | awk '{print $NF}' | grep .gz$ | tr '\n' ' '`;
for f in $files
do
echo "available files are: $f"
filename=$(hadoop fs -ls $f | awk -F '/' '{print $NF}' | head -1)
hdfs dfs -cat $f | gzip -d | hdfs dfs -put - $unziped_dir"/"${filename%.*}
echo "unziped file names: ${filename%.*}"
done
输出:
开发:
available files are: s3://2019-01-03/File_2019-01-03.CSV.gz
unziped file names: File_2019-01-03.CSV
available files are: s3://2019-01-03/Data_2019-01-03.CSV.gz
unziped file names: Data_2019-01-03.CSV
available files are: s3://2019-01-03/Output_2019-01-03.CSV.gz
unziped file names: Output_2019-01-03.CSV
PROD:
available files are: s3://2019-01-03/File_2019-01-03.CSV.gz s3://2019-01-03/Data_2019-01-03.CSV.gz s3://2019-01-03/Output_2019-01-03.CSV.gz
unziped file names:
我试图查看目录并识别.gz文件并迭代它们以解压缩所有.gz文件并存储到不同的目录中。但是当我在EMR开发集群中运行此脚本时,它的工作正常。但是在生产集群中却没有。请查看上面脚本的行为。
for f in $files
中的单词分裂似乎存在问题。通常情况下,shell应该像在Dev上那样在空格处分割值$files
。在开发f
被设置为$files
循环的每个循环中for
的三个单词之一,在Prod f
获得包括空格的$files
的完整值。
你在某处设置变量IFS
吗?
如果问题不在脚本的其他部分,您应该能够使用简化的脚本重现问题:
files="foo bar baz"
for f in $files
do
echo "available files are: $f"
done
如果此最小脚本没有显示差异,则问题出现在脚本的其他部分中。
要查看在Dev和Prod上IFS
的值是否不同,您可以在for
循环之前将其添加到最小脚本或原始脚本:
# To see if IFS is different. With the default value (space, tab, newline) the output should be
# 0000000 I F S = # \t \n # \n
# 0000012
echo "IFS=#${IFS}#" | od -c
如果你看到IFS
值的差异,你必须找出IFS
被修改的位置。
BTW:通常你可以在grep命令后省略| tr '\n' ' '
。在处理\n
时,shell应该接受for f in $files
作为单词拆分字符。如果没有,这可能与您的问题的根源有关。
编辑:有一个更好的解决方案来逐行处理数据,请参阅 https://mywiki.wooledge.org/DontReadLinesWithFor和 https://mywiki.wooledge.org/BashFAQ/001
你应该使用while read
...而不是for
...
修改后的脚本(未经测试)
output_path=s3://output
unziped_dir=s3://2019-01-03
hadoop fs -ls "$output_path"/ | awk '{print $NF}' | grep .gz$ | while IFS= read -r f
do
echo "available files are: $f"
filename=$(hadoop fs -ls "$f" | awk -F '/' '{print $NF}' | head -1)
hdfs dfs -cat "$f" | gzip -d | hdfs dfs -put - "${unziped_dir}/${filename%.*}"
echo "unziped file names: ${filename%.*}"
done