我目前正在编写以下脚本。该代码在某个目录中查找用户输入的文件名。该脚本首先检查输入文件是否是 gzip,如果是,则运行相应的检查。如果文件未经过 gzip 压缩,则会返回不兼容的文件文本。
我遇到的问题是在线的7
。无论文件扩展名如何,我都会收到不兼容的文件作为最终输出。
#!/bin/bash
DATE=$(date +%Y-%m-%d)
L0_Report_Generator=("/home/ubuntu/$gzip_file")
echo -n "Enter File Directory:"$gzip_file
read $gzip_file
for gzip_file in {$L0_Report_Generator}; do
if [[ $gzip_file = "test_sub"*"gz" ]] #Check file extension for gzip compression
then
gunzip $gzip_file
echo "file Level 0 QC Check"
echo ${DATE}
echo "File Header"
cat $gzip_file | head
echo "Total Records"
cat $gzip_file | wc -l
echo "File Unique Records Size"
cat $L0_Report_Generator | sort -u | wc -l
rm $gzip_file
else [[ $gzip_file != "test_sub"*"gz" ]] #If file is anything other than .gz and csv - rort will not run
then
echo "incompatible file"
fi
done
答案1
如果您想在 if 语句中使用通配符表达式来检查“.gz”文件扩展名,那么您可以使用如下所示的表达式:
if [[ "${gzip_file}" = *.gz ]]; then echo true; else echo false; fi
您可以通过以下方式进行测试:
if [[ "file.gz" = *.gz ]]; then echo true; else echo false; fi
和:
if [[ "file.txt" = *.gz ]]; then echo true; else echo false; fi
第一个示例生成true
其输出,第二个示例生成false
。
现在让我们看看您的代码。您的 if 语句具有以下条件表达式:
[[ $gzip_file = "test_sub"*"gz" ]]
特别是,您将“test_sub”作为子字符串包含在匹配模式中。尝试删除它。
答案2
除了 @igal 所说的有关检查文件扩展名的内容之外,您在变量语法和用法方面还有很多错误。从第 3 行开始:
L0_Report_Generator=("/home/ubuntu/$gzip_file")
该变量gzip_file
尚未设置,因此$gzip_file
当 shell 展开它时将不会被任何内容替换。另外,中的括号var=(something)
分配一个数组而不是一个普通变量,在这种情况下,这没有任何意义。
第四行 ,echo -n "Enter File Directory:"$gzip_file
变量 也有同样的问题gzip_file
。它还存在不可预测的问题echo -n
,在不同版本的命令下会做不同的事情echo
。要打印没有换行符的字符串,最好使用printf "%s" "string to print"
,但在这种情况下,有一个更好的选择,我稍后会介绍。
第五行read $gzip_file
似乎旨在将用户输入读取到变量 中gzip_file
,但这不是它的作用。在 shell 中,当你放在$
变量名前面时,得到变量的当前值。在这里,你想要放它,所以你必须保留$
off: read gzip_file
。但这不是我会做的。我将包含提示(echo
在第 4 行)作为read
命令的一部分:
read -p "Enter File Directory:" gzip_file
好的,现在是第 6 行:
for gzip_file in {$L0_Report_Generator}; do
这似乎是设置gzip_file
再次read
(替换我们刚刚输入的值)。您实际上是否尝试在此处设置gzip_file
,并且之前的变量引用确实应该是不同的变量(也许gzip_dir
相反)?
而且,这in
部分没有任何意义。我认为您正在尝试使用变量L0_Report_Generator
,但在这种情况下,左大括号应该去后美元符号。但这也不完全有意义,因为${L0_Report_Generator}
(如果我明白这应该做什么)只是目录的路径。for ... in
不迭代目录的内容,而是迭代列表字, 喜欢for var in word1 word2 "word 3 which has several spaces in it" word4; do
。如果要获取目录中的文件列表,则需要使用通配符,例如for var in dir/*; do
-- shell 会将包含通配符的文件模式扩展为匹配文件的列表,每个文件都被视为一个单词,并迭代它们。您还可以选择通过将特定扩展名包含在模式中来限制对具有特定扩展名的文件的匹配,例如dir/*.gz
.
其他三个注意事项:我建议不要使用大写变量名称,例如DATE
, 以避免与对 shell 或某些实用程序具有特殊含义的各种全大写环境变量发生冲突。另外,始终用双引号引用变量(即使用"$var"
而不是仅仅$var
)以避免意外的解析异常。并且该else
子句没有测试,因此 usingelse [[ some test ]]
没有意义(并且then
afterelse
是语法错误)。
因此,如果我理解脚本应该做什么,我建议将脚本的开头替换为:
#!/bin/bash
date=$(date +%Y-%m-%d) # Note lowercase variable
read -p "Enter File Directory:" gzip_dir
L0_Report_Generator="/home/ubuntu/$gzip_dir"
for gzip_file in "${L0_Report_Generator}"/*.gz; do
...然后(如果上面的 .gz 模式是您想要的),您不需要if
检查是否$gzip_file
具有 .gz 扩展名,因为通配符模式只会列出 .gz 文件。
还要注意一点:shellcheck.net对于指出 shell 脚本中的基本错误非常有帮助。它错过了我指出的很多内容,但抓住了迷路then
(我最初错过了)。