代码之家  ›  专栏  ›  技术社区  ›  StevieD

script to git提交多个文件的列表,文件名中有空格或没有空格

  •  0
  • StevieD  · 技术社区  · 5 年前

    我有这个功能:

    git_commit () {
        if [[ $# -eq 0 || ( $# -eq 1 && $1 == '.' ) ]]
        then
            git commit .
        else
            commit_string=''
            for var in "$@"
            do
          ! [[ $var =~ ^[0-9]+$ ]] && { echo "Supply integer values from the menu only. Nothing added." && return; }
          file="$(git status -s|awk 'FNR == '$var'{$1="";print $0}')";
          file=$(sed -e 's/^[[:space:]]*//' <<<"$file")
          new_file="${file} "
          commit_string+=${new_file}
    
            done
        echo $commit_string;
            read -ep "Commit description: " desc
        commit_string=${commit_string##*( )}
        commit_string="${commit_string//\"}"
        git commit -m "$desc" ${commit_string}
        fi
      git_short_status
    
    }
    

    该函数生成一个由我用菜单选择的文件名组成的字符串。例子:

    get_commit 1 3 5
    

    在这种情况下,它将运行:

    git commit -m 'description from prompt' file_1 file file_3 file_5
    

    我很难弄明白如何让函数处理文件中有空格的文件。问题在于:

    git commit -m "$desc" ${commit_string}
    

    这一行适用于多个没有空格的文件。然而,它被一个带有空格的文件阻塞了。所以我把它改成:

    git commit -m "$desc" "${commit_string}"
    

    像这样,它适用于有空格的文件,但当我有多个文件时会阻塞(我得到一个错误,它无法识别文件路径)。

    0 回复  |  直到 5 年前
        1
  •  3
  •   Gordon Davisson    5 年前

    在变量中嵌入转义符、引号等是不正确的,因为shell解析转义符等 之前 它扩展了变量;因此,当escape/whatever成为命令的一部分时,它已经来不及做任何有用的事情了。

    如果需要在一个变量中存储多个项(例如文件名),更好的方法是使用数组,将每个项存储为单独的数组元素,然后使用以下语法扩展数组 "${arrayname[@]}" .

    我不知道该怎么做 git status -s 报告带有空格的文件,但我认为这应该有效:

    git_commit () {
        if [[ $# -eq 0 || ( $# -eq 1 && $1 == '.' ) ]]
        then
            git commit .
        else
            commit_array=()    # This creates an empty (zero-element) array
            for var in "$@"
            do
          ! [[ $var =~ ^[0-9]+$ ]] && { echo "Supply integer values from the menu only. Nothing added."; return; }
          file="$(git status -s|awk -v var="$var" 'FNR == var {$1="";print $0}')";
          file=$(sed -e 's/^[[:space:]]*//' <<<"$file")
          commit_array+=("${file}")    # Add a new element. The +=, (), and double-quotes are required for this to work right.
    
            done
        printf "%q " "${commit_array[@]}"    # Print the elements in "quoted" form
        echo    # The printf doesn't print a newline; so do that
            read -ep "Commit description: " desc
        git commit -m "$desc" "${commit_array[@]}"
        fi
      git_short_status
    
    }
    

    我还改变了 && ; 在错误返回中,因为如果 echo 不管怎样,如果你成功地失败了,你仍然想要回归,而不是继续。而且,我改变了方式 $var 传给 awk 以更安全的形式(尽管在这种情况下这并不重要)。(实际上,整个 awk ... sed 比特可以清理一下,但我会留下它……)

        2
  •  0
  •   John Kugelman Michael Hodel    5 年前

    这就解决了问题:

    bash -c "git commit -m \"$desc\" ${commit_string}"
    

    虽然我不太清楚为什么。

    推荐文章