linux - BASH for循环在调用函数后退出

标签 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 会如何影响它?如果我注释掉该行,它会按预期工作。

最佳答案

如果你想让 i 是本地的,你需要这样声明它:

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

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

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

关于linux - BASH for循环在调用函数后退出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43194914/

相关文章:

linux - 如何添加详细选项来控制脚本输出?

linux - 如何在 Unix 命令行上定位用户

linux - httpd/apachectl 服务无法在 RHEL 7 上启动

bash - tee 命令通过 grep 管道传输并重定向到文件

linux - CouchDB 更改数据库目录

bash - 处理除第一个参数之外的所有参数(在 bash 脚本中)

linux - 在 bash 中,点命令和符号有什么作用?

linux|awk|shell脚本 block 删除

linux - 在 Debian 8 上将 TeamSpeak3 作为服务运行

OSX 上的 Python os.getenv (Django 1.4)