我有一个函数,save
它被for
循环中的其他函数调用,该函数是融合特定目录中相同类型的文件(根据每个文件的内容逐行复制到一个新文件)到他们的类型)。
融合文件的名称采用${x}_type_${y}.log
以下格式:x
和y
是来自调用函数 save 的其他函数的变量,类型是文件的类型。
我尝试使用cat
,echo
和paste
来融合文件,但它们都不起作用。当我运行脚本时,融合的文件根据融合的文件类型携带代码中设置的名称,但融合的文件为空,或者包含应该融合的文件的名称而不是其内容。
for file in *;
do
type=$( echo "$file" | awk -F'[.-]' '{print $2}' )
save () {
if [[ "$type" == "$type1" ]];
then
cat "$file" >> "${x}_First_${y}.log"
elif [[ "$type" == "$type2" ]];
then
cat "$file" >> "${x}_Second_${y}.log"
elif [[ "$type" == "$type3" ]];
then
cat "$file" >> "${x}_Third_${y}.log"
elif [[ "$type" == "$type4" ]];
then
cat "$file" >> "${x}_Fourth_${y}.log"
else
echo "Nothing to do"
fi
}
done
我也尝试过将每个文件的内容逐行复制到新文件中,但它仍然不起作用。
for file in *;
do
type=$( echo "$file" | awk -F'[.-]' '{print $2}' )
save () {
if [[ "$type" == "$type1" ]];
then
while IFS= read -r line
do
echo "$line"
echo -e "$line\n" >>"${x}_Request_${y}.log"
done <"$file"
elif [[ "$type" == "$type2" ]];
then
while IFS= read -r line
do
echo "$line"
echo -e "$line\n" >>"${x}_Error_${y}.log"
done <"$file"
elif [[ "$type" == "$type3" ]];
then
while IFS= read -r line
do
echo "$line"
echo -e "$line\n" >>"${x}_Critical_${y}.log"
done <"$file"
elif [[ "$type" == "$type4" ]];
then
while IFS= read -r line
do
echo "$line"
echo -e "$line\n" >>"${x}_Test_${y}.log"
done <"filename"
else
echo "Nothing to do"
fi
}
done
这是整个脚本
#!/bin/bash
env1="dev"
env2="prod"
type1="request"
type2="error"
type3="critical"
type4="test"
save () {
if [[ "$type" == "$type1" ]];
then
cat "$file" >> "${m}_Request_${w}.log"
elif [[ "$type" == "$type2" ]];
then
cat "$file" >> "${m}_Error_${w}.log"
elif [[ "$type" == "$type3" ]];
then
cat "$file" >> "${m}_Critical_${w}.log"
elif [[ "$type" == "$type4" ]];
then
cat "$file" >> "${m}_Test_${w}.log"
else
echo "Nothing to do"
fi
}
week_range () {
if [[ "$day" -ge 1 && "$day" -le 7 ]];
then
w="Wk1"
save
elif [[ "$day" -ge 8 && "$day" -le 14 ]];
then
w="Wk2"
save
elif [[ "$day" -ge 15 && "$day" -le 21 ]];
then
w="Wk3"
save
elif [[ "$day" -ge 22 && "$day" -le 28 ]];
then
w="Wk4"
save
elif [[ "$day" -ge 29 && "$day" -le 31 ]];
then
w="Wk5"
save
else
echo "Nothing to do"
fi
}
month_range () {
if [[ "$month" -eq 1 ]];
then
m="Jan"
week_range
elif [[ "$month" -eq 2 ]];
then
m="Feb"
week_range
elif [[ "$month" -eq 3 ]];
then
m="Mar"
week_range
elif [[ "$month" -eq 4 ]];
then
m="Apr"
week_range
elif [[ "$month" -eq 5 ]];
then
m="May"
week_range
elif [[ "$month" -eq 6 ]];
then
m="Jun"
week_range
elif [[ "$month" -eq 7 ]];
then
m="Jul"
week_range
elif [[ "$month" -eq 8 ]];
then
m="Aug"
week_range
elif [[ "$month" -eq 9 ]];
then
m="Sep"
week_range
elif [[ "$month" -eq 10 ]];
then
m="Oct"
week_range
elif [[ "$month" -eq 11 ]];
then
m="Nov"
week_range
elif [[ "$month" -eq 12 ]];
then
m="Dec"
week_range
else
echo "Nothing to do"
fi
}
for file in *.log;
do
env=$( echo "$file" | awk -F'[.-]' '{print $1}' )
type=$( echo "$file" | awk -F'[.-]' '{print $2}' )
month=$((10#$( echo "$file" | awk -F'[.-]' '{print $4}' )))
day=$((10#$( echo "$file" | awk -F'[.-]' '{print $5}' )))
if [[ "$env" == "$env1" ]];
then
cd Env1 && { month_range; cd -; }
elif [[ "$env" == "$env2" ]];
then
cd Env2 && { month_range; cd -; }
else
echo "Nothing to do"
fi
done
这就是我的文件的样子
dev.critical-2021-01-05.log prod.critical-2021-12-07.log
dev.critical-2021-08-09.log prod.error-2021-02-21.log
dev.error-2021-08-01.log prod.error-2021-07-29.log
dev.error-2021-08-07.log prod.error-2021-10-22.log
dev.request-2021-08-01.log prod.request-2021-01-02.log
dev.request-2021-08-12.log prod.request-2021-04-10.log
dev.test-2021-09-03.log
这就是我期望在不同目录中的 dev 和 prod 所拥有的
Jan_Critical_Wk1.log
Jan_Request_Wk1.log
Jun_Request_Wk1.log
Mar_Critical_Wk2.log
May_Error_Wk2.log
Feb_Error_Wk3.log
Apr_Request_Wk2.log
Aug_Critical_Wk1.log
Aug_Critical_Wk2.log
Aug_Error_Wk1.log
Aug_Error_Wk2.log
Aug_Request_Wk1.log
Aug_Request_Wk2.log
Nov_Error_Wk3.log
Oct_Error_Wk4.log
Sep_Request_Wk4.log
Jul_Error_Wk5.log
Sep_Test_Wk1.log
答案1
您的错误是在移动到该文件不可用的另一个目录后尝试引用所cat
引用的文件。$file
您似乎检查了文件名并据此对它们进行分类。
代码可以变得更简单。
#!/bin/bash
shopt -s nullglob
declare -A envdir
months=( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec )
envdir=( [dev]=Env1 [prod]=Env2 )
for name in *.log; do
IFS='.-' read -r env type year month day suffix <<<"$name"
m=${months[(10#$month) - 1]}
w="Wk$(( 1 + (10#$day)/7 ))"
if [ -z "$m" ] || [ ! -d "${envdir[$env]}" ]; then
echo 'Nothing to do'
continue
fi
cat -- "$name" >>"${envdir[$env]}/${m}_${type^}_$w.log"
done
上面使用的事实是类型的目录名称已经是文件名的一部分。我们只需要大写初始字符,我们用 来实现${type^}
。文件名的不同部分使用 读入变量read
。
我们根据月份编号从数组中选择月份名称,而不是遍历一长串if
, then
,else
列表。周数是根据天计算的。要使用的环境目录存储在关联数组 中envdir
。
我们不需要cd
去任何地方。
nullglob
如果不匹配任何内容,shell 选项会使通配模式完全消失。如果没有nullglob
,模式*.log
将被分配给name
并且至少会发生一次循环迭代。
您还可以对选择文件名的方式进行更多限制,以确保只选择有效的文件。
#!/bin/bash
shopt -s nullglob extglob
declare -A envdir
months=( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec )
envdir=( [dev]=Env1 [prod]=Env2 )
for name in @(dev|prod).@(critical|error)-????-??-??.log; do
# as before
done
请注意添加了extglob
shell 选项。它允许我们编写ksh
类似扩展的通配模式来匹配我们想要查看的特定名称。特别是,它允许我们用来@(pattern|pattern|pattern)
匹配所包含的模式或字符串之一。