调用函数

时间:2017-04-03 21:50:53

标签: linux bash shell

我正在处理bash脚本,这些脚本基本上会移动目录的全部内容,其中文件名都以数字(0001,0002等)开头。我通过这些文件以相反的顺序迭代,先将最后一个文件向下移动。

我有一个函数遍历文件并调用另一个函数来实际移动它们。当我调用第二个函数时,它会使for循环短路并退出。我无法弄清楚原因。

validation_dir="scripts/validation"
content_directories=($validation_dir "tutorials")

function shift_contents() {
    local start_index=$1
    local positions=$2

    local files=(${validation_dir}/*)
    for ((i=${#files[@]}-1; i>=0; i--)); do
        # Only gets called once
        echo $i
        local f="${files[$i]}"
        local old_index=$(echo $f | tr -dc '0-9' | sed -e 's/^0*//')
        if [ "$old_index" -lt "$start_index" ]
        then
            # Only start when we're at the start index
            continue
        fi
        local new_index=$((old_index + positions))
        # When this is called, it exits the loop
        move_exercise $old_index $new_index
    done
}

这是进行转移的功能:

function move_exercise() {
    local start_index=$1
    local end_index=$2
    local start_prefix=$(echo_filename_prefix $start_index)
    local end_prefix=$(echo_filename_prefix $end_index)

    for i in ${content_directories[@]}; do
        start_file_glob="${i}/${start_prefix}*"

        for f in $start_file_glob; do
            if [ -e $f ]
            then
                start_filename=$f
            else
                log_error "No content found with index ${start_index}"
                exit 1
            fi
            break
        done

        end_file_glob="${i}/${end_prefix}*"

        if [ -e $end_file_glob ]
        then
            log_error "Content was already found for end index ${end_index}: ${end_file_glob}"
            exit 1
        fi

        # Generate the new file name
        new_filename="${start_filename/$start_prefix/$end_prefix}"
        # We get down here once
        echo $start_filename $new_filename
    done

    return
}

看起来第二个功能导致第一个功能提前退出,但我不知道这是怎么回事。看看发生了什么?

编辑:

当我使用bash -x script.sh运行时,当它应该再进行一次迭代时,它以以下输出结束:

+ echo path/to/second-to-last-file new-path
+ return
+ (( i-- ))
+ (( i>=0 ))

这是否意味着它未通过for循环条件检查?如果是这样,move_exercise怎么会影响到那个?如果我注释掉那一行,它会按预期工作。

1 个答案:

答案 0 :(得分:2)

如果您希望i是本地的,则需要将其声明为:

shift_contents() {
  local i
  # ...etc...
}

move_exercise() {
  local i
  # ...etc...
}

否则,两个函数之间只共享一个名为i的变量。当该变量包含文件名时,其数值为0(除非该文件名也是分配了非零数值的shell变量的名称) - 所以当您在分配文件名后递减它时,它将变为负数。