function generateFileList {
for entry in "$ORIGINATION_PATH"/*
do
entry=${entry%.*} # retain the part before the dot
entry=${entry##*/} # retain the part after the last slash
if [ $(contains "${FILENAME[@]}" $entry) == "n" ]; then
FILENAME[$fn_counter]=$entry
fn_counter=(expr $fn_counter + 1)
echo $entry "added to filelist"
echo ${FILENAME[$fn_counter]}
fi
done
NUMBER_OF_FILES=$(expr ${#FILENAME[@]} + 1)}
我有这个功能。我的$ ORIGINATION_PATH里面有很多文件。但是,当我调用此函数时,我的$ FILENAME数组只会填充一个条目。为什么?在函数内部一切似乎都很好,似乎$ FILENAME数组获取了它需要获取的所有值,但是当我在函数外部检查时,我只在$ FILENAME aray中获得一个值
答案 0 :(得分:1)
代码问题和改进建议:
${FILENAME[@]}
初始化为空数组(如果您始终希望函数从头开始生成新的文件列表,或者在您希望能够构建之前调用该函数,则可以在函数本身中初始化通过在不同的基目录上重复调用该函数来获取文件的复合列表。)$fn_counter
初始化为零。或者,对于复合构建思想,当前在${FILENAME[@]}
中的元素数量。实际上,另一个可能更好的解决方案是完全删除$fn_counter
变量并将其替换为${#FILENAME[@]}
,因为它应该始终等于该值。fn_counter=(expr $fn_counter + 1)
中,您将$fn_counter
分配给数组,而不是递增它。这是因为你在开括号前忘记了美元。如果您运行fn_counter=$(expr $fn_counter + 1)
,那么它会起作用。但是有一种更好的方法来增加数字变量:let ++fn_counter
。${FILENAME[fn_counter]}
而不是${FILENAME[$fn_counter]}
。${FILENAME[@]}
元素,但在之后使用$fn_counter
对其进行索引会增加,这是不正确的。您可以通过从中减去1来解决此问题,即echo "${FILENAME[fn_counter-1]}"
。或者,如果删除$fn_counter
,echo "${FILENAME[${#FILENAME[@]}-1]}"
。$NUMBER_OF_FILES
时,我不知道你为什么要向${#FILENAME[@]}
添加1。 ${FILENAME[@]}
数组中的元素数应该等于文件数,不需要增量,不是吗?我建议完全删除此变量,因为该值可以直接以${#FILENAME[@]}
。$ORIGINATION_PATH
作为参数传递)并使用local
关键字来降低函数之间变量冲突的可能性。全局变量是bash中的默认值,它为不同的函数创建了危险的可能性,以便踩到彼此的脚趾。例如,假设contains
函数(假设它是一个shell函数)为全局$entry
变量赋值。[[
命令而不是[
,因为它更强大,并且保持一致性很好。[[ -n "$(find "$ORIGINATION_PATH" -maxdepth 0 -empty)" ]]
),您可以提前测试。另一种解决方案是设置nullglob
。另一个解决方案是跳过实际不存在的glob字(例如if [[ ! -e "$entry" ]]; then continue; fi;
)。contains
调用应为contains "${FILENAME[@]}" "$entry"
(请注意$entry
周围的双引号)。唯一的例外是(1)将字符串变量分配给字符串变量,即new=$old
,在这种情况下,您不必引用它,以及(2)扩展数字变量时,保证不被分词破坏。这是一个有效的解决方案,填补了缺失的部分:
function contains {
local target="${@:$#:1}";
local -a array=("${@:1:$#-1}");
local elem='';
for elem in "${array[@]}"; do
if [[ "$elem" == "$target" ]]; then
echo 'y';
return;
fi;
done;
echo 'n';
} ## end contains()
function generateFileList {
local path="$1";
local entry='';
for entry in "$path"/*; do
if [[ ! -e "$entry" ]]; then continue; fi;
entry=${entry%.*}; ## retain the part before the dot
entry=${entry##*/}; ## retain the part after the last slash
if [[ "$(contains "${FILENAME[@]}" "$entry")" == 'n' ]]; then
FILENAME[${#FILENAME[@]}]=$entry;
echo "$entry added to filelist";
echo "${FILENAME[${#FILENAME[@]}-1]}";
fi;
done;
} ## end generateFileList()
ORIGINATION_PATH='...';
FILENAME=(); ## build up result on global ${FILENAME[@]} var
generateFileList "$ORIGINATION_PATH";
echo "\${#FILENAME[@]} == ${#FILENAME[@]}";
echo "\${FILENAME[@]} == (${FILENAME[@]})";