如何将Maven项目版本添加到bash命令行

时间:2010-08-23 06:53:31

标签: maven-2 command-line

上一篇文章我在how to change Maven project vesion from command line上发了一个问题,引出了一个新问题。

之前我能够获得版本号,因为版本存储为易于grep并从命令行解析的属性(bash)。现在pom.xml元素已用于此,它不再是唯一的,因为所有依赖项和其他一些也使用它。我认为没有办法使用bash脚本获取当前版本号,而不使用外部工具来解析xml或一些非常上下文的sed命令。

我认为最干净的解决方案是让Maven分发这个版本信息。我正在考虑编写一个自定义maven插件来检索不同的属性,但我想我先问这里。

那么,是否有任何简单的方法可以将${project.version}的值赋予命令行?提前谢谢。

解决方案

感谢您的帮助。我必须手动cd到目录,但这可以很容易地完成。在我的bash脚本中我有

version=`cd $project_loc && mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | sed -n -e '/^\[.*\]/ !{ /^[0-9]/ { p; q } }'`

这给了我当前版本,然后我可以推进。 Grepping可能更简单,但我认为我希望尽可能健壮,所以我对以数字开头的第一行感到满意,并尝试将其作为版本号处理。

# Advances the last number of the given version string by one.
function advance_version () {
    local v=$1
    # Get the last number. First remove any suffixes (such as '-SNAPSHOT').
    local cleaned=`echo $v | sed -e 's/[^0-9][^0-9]*$//'`
    local last_num=`echo $cleaned | sed -e 's/[0-9]*\.//g'`
    local next_num=$(($last_num+1))
    # Finally replace the last number in version string with the new one.
    echo $v | sed -e "s/[0-9][0-9]*\([^0-9]*\)$/$next_num/"
}

我只需拨打

即可使用此功能
new_version=$(advance_version $version)

希望这有助于某人。

32 个答案:

答案 0 :(得分:185)

Maven Help Plugin已经在某种程度上为此提出了一些建议:

  
      
  • help:evaluate评估用户以交互模式提供的Maven表达式。
  •   

以下是在命令行上调用它以获取${project.version}

的方法
mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate \
    -Dexpression=project.version

答案 1 :(得分:168)

汤姆使用Exec Maven Plugin的解决方案要好得多,但仍然比它需要的更复杂。对我而言,它很简单:

MVN_VERSION=$(mvn -q \
    -Dexec.executable=echo \
    -Dexec.args='${project.version}' \
    --non-recursive \
    exec:exec)

答案 2 :(得分:44)

mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | grep -v '\['

答案 3 :(得分:34)

我一直在做一些研究,发现了以下内容:

  1. Maven因系统操作脚本中的不易集成而受到指责,因为它没有遵循一些关于CLI工具的良好实践。 (参考:https://youtu.be/1ILEw6Qca3U?t=372

  2. 受到前一个断言的启发,我决定看看maven的源代码以及maven-help-plugin。似乎他们已经修改了一点maven的-q开关(我使用的是3.5.3版),所以现在如果你通过它,你就不会得到所有恼人的非感知日志记录的东西这可以防止maven在自动脚本中使用。所以你应该可以使用这样的东西:

    mvn help:evaluate -Dexpression=project.version -q
    

    问题是此命令不打印任何内容,因为默认情况下,帮助插件通过-q开关静音的记录器输出。 (该插件的最新可用版本是在2018年6月3日发布的3.1.0)

  3. Karl Heinz Marbaise(https://github.com/khmarbaise)通过添加一个可选参数来修复它,允许您通过以下方式调用它:

    mvn help:evaluate -Dexpression=project.version -q -DforceStdout
    

    提交说明位于:(https://github.com/apache/maven-help-plugin/commit/316656983d780c04031bbadd97d4ab245c84d014

答案 4 :(得分:34)

在我看来,最重要的答案是非常垃圾,你必须使用一堆grep来破解maven控制台输出。为什么不使用合适的工具呢?使用xpath语法是检索版本号的最佳方法,因为它是访问XML数据结构的预期方法。下面的表达式是使用"本地名称"遍历pom。这些元素,换句话说,忽略了xml中可能存在或不存在的名称空间声明。

xmllint --xpath "//*[local-name()='project']/*[local-name()='version']/text()" pom.xml

答案 5 :(得分:26)

这样可以避免从输出中删除日志条目:

{{1}}

答案 6 :(得分:12)

python -c "import xml.etree.ElementTree as ET; \
  print(ET.parse(open('pom.xml')).getroot().find( \
  '{http://maven.apache.org/POM/4.0.0}version').text)"

只要你有python 2.5或更高版本,这应该工作。如果版本低于此版本,请安装python-lxml并将导入更改为lxml.etree。这种方法很快,不需要下载任何额外的插件。它也适用于不能用xmllint验证的格式错误的pom.xml文件,就像我需要解析的那样。在Mac和Linux上测试过。

答案 7 :(得分:9)

在这里使用其他一些答案时,我一直遇到不好的情况,所以这是另一种选择。

version=$(printf 'VER\t${project.version}' | mvn help:evaluate | grep '^VER' | cut -f2)

答案 8 :(得分:7)

如果您不介意将版本写入临时文件,那么另一种解决方案(没有grep / sed)对我来说效果很好。 (编辑:请参阅rjrjr's answer了解更简单的解决方案,无需任何临时文件麻烦)

我使用Exec Maven Pluginecho二进制文件。与Maven帮助插件相比,Exec插件允许输出重定向到一个文件,可用于绕过grep / sed,甚至可以解析奇怪的东西,如多行版本字符串(版本标签中带有CDATA块),至少在一定程度上。

#!/usr/bin/env sh

MVN_VERSION=""
VERSION_FILE=$( mktemp mvn_project_version_XXXXX )
trap "rm -f -- \"$VERSION_FILE\"" INT EXIT

mvn -Dexec.executable="echo" \
    -Dexec.args='${project.version}' \
    -Dexec.outputFile="$VERSION_FILE" \
    --non-recursive \
    --batch-mode \
    org.codehaus.mojo:exec-maven-plugin:1.3.1:exec > /dev/null 2>&1 ||
    { echo "Maven invocation failed!" 1>&2; exit 1; }

# if you just care about the first line of the version, which will be
# sufficent for pretty much every use case I can imagine, you can use
# the read builtin
[ -s "$VERSION_FILE" ] && read -r MVN_VERSION < "$VERSION_FILE"

# Otherwise, you could use cat.
# Note that this still has issues when there are leading whitespaces
# in the multiline version string
#MVN_VERSION=$( cat "$VERSION_FILE" )

printf "Maven project version: %s\n" "$MVN_VERSION"

答案 9 :(得分:5)

我注意到输出中有一些伪造的Downloaded:行正在破坏我的原始作业。这是我已经确定的过滤器;希望它有所帮助!

version=$(mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | egrep -v '^\[|Downloading:' | tr -d ' \n')

修改

不是100%确定原因,但是当通过Jenkins中的后期构建脚本运行时,输出结果为[INFO]version,例如[INFO]0.3.2

我将输出转储到一个文件并直接从BASH通过我的第一个过滤器运行它,它工作得很好..所以再次,不确定Jenkins土地上发生了什么。

为了在Jenkins中100%获得它,我添加了一个后续sed过滤器;这是我最新的

version=$(mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | egrep -v '^\[|Downloading:' | tr -d ' \n' | sed -E 's/\[.*\]//g')

修改

最后一点说明..我发现tr 仍然导致/r/n0.3.2之类的事情(仅在通过Jenkins运行时)。切换到awk,问题就消失了!我的最终工作结果

mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version \
| egrep -v '^\[|Downloading:' | sed 's/[^0-9\.]//g' | awk 1 ORS=''

答案 10 :(得分:5)

简单的maven唯一解决方案

mvn -q -N org.codehaus.mojo:exec-maven-plugin:1.3.1:exec \
    -Dexec.executable='echo' \
    -Dexec.args='${project.version}'

奖励积分解析部分版本

mvn -q -N org.codehaus.mojo:build-helper-maven-plugin:3.0.0:parse-version \
    org.codehaus.mojo:exec-maven-plugin:1.3.1:exec \
    -Dexec.executable='echo' \
    -Dexec.args='${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}'

答案 11 :(得分:5)

只是为了记录,可以直接在命令行中配置Maven的简单SLF4J日志记录,以便仅通过配置输出我们需要的内容:

  • or
  • org.slf4j.simpleLogger.defaultLogLevel=WARN

http://www.slf4j.org/api/org/slf4j/impl/SimpleLogger.html

中记录
org.slf4j.simpleLogger.log.org.apache.maven.plugins.help=INFO

因此,可以只运行MAVEN_OPTS="\ -Dorg.slf4j.simpleLogger.defaultLogLevel=WARN \ -Dorg.slf4j.simpleLogger.log.org.apache.maven.plugins.help=INFO" \ mvn help:evaluate -o -Dexpression=project.version 并获取:

tail -1

请注意,这是一个单行。 $ MAVEN_OPTS="\ -Dorg.slf4j.simpleLogger.defaultLogLevel=WARN \ -Dorg.slf4j.simpleLogger.log.org.apache.maven.plugins.help=INFO" \ mvn help:evaluate -o -Dexpression=project.version | tail -1 1.0.0-SNAPSHOT 仅针对此特定MAVEN_OPTS执行进行重写。

答案 12 :(得分:4)

我最近开发了Release Candidate Maven插件,解决了这个问题,因此您不必诉诸任何hacky shell脚本并解析maven-help-plugin的输出

例如,要将Maven项目的版本打印到终端,请运行:

mvn com.smartcodeltd:release-candidate-maven-plugin:LATEST:version

,其输出类似于maven-help-plugin

[INFO] Detected version: '1.0.0-SNAPSHOT'
1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

但是,您也可以指定任意输出格式(以便CI服务器(例如TeamCity)可以从日志中获取版本):

mvn com.smartcodeltd:release-candidate-maven-plugin:LATEST:version \
   -DoutputTemplate="##teamcity[setParameter name='env.PROJECT_VERSION' value='{{ version }}']"

结果是:

[INFO] Detected version: '1.0.0-SNAPSHOT'
##teamcity[setParameter name='env.PROJECT_VERSION' value='1.0.0-SNAPSHOT']
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

将输出保存到文件中(以便Jenkins等CI服务器可以use it):

mvn com.smartcodeltd:release-candidate-maven-plugin:LATEST:version \
   -DoutputTemplate="PROJECT_VERSION={{ version }}" \
   -DoutputUri="file://\${project.basedir}/version.properties"

生成的version.properties文件如下所示:

PROJECT_VERSION=1.0.0-SNAPSHOT

除上述所有内容外,Release Candidate还允许您设置项目的版本(这是您可能在CI服务器上执行的操作)基于您在POM中定义的API版本。

如果您希望看到Release Candidate的示例被用作Maven生命周期的一部分,请查看我的其他开源项目的pom.xml - Build Monitor for Jenkins

答案 13 :(得分:3)

这是我发现的最干净的解决方案

mvn org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout

在所有操作系统上都可以正常工作。不需要任何外部工具!

-q禁止显示详细消息。 maven-help-plugin3.2.0(及更高版本)具有forceStdout选项。

答案 14 :(得分:3)

易于理解的一体化解决方案,可输出maven项目版本,并抑制来自[INFO]Download消息的无关输出:

mvn -o org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | grep -v '\['

同样的事情,但分成两行:

mvn -o org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate \
      -Dexpression=project.version | grep -v '\['

输出:4.3-SNAPSHOT

所以,在简单的bash脚本中使用project.version

projectVersion=`mvn -o org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate -Dexpression=project.version | grep -v '\['`
cd "target/"$projectVersion"-build"

此页面上的其他解决方案似乎并未将所有技巧合二为一。

答案 15 :(得分:2)

应该更容易,因为maven-help-plugin 3.0.0中修复了这个错误:MPH-99 Evaluate has no output in quiet mode

答案 16 :(得分:2)

这是迄今为止最简单的bash剪切和粘贴解决方案:

VERSION=$(mvn -Dexec.executable='echo' -Dexec.args='${project.version}' --non-recursive exec:exec -q)
echo $VERSION

它回响

1.4

答案 17 :(得分:2)

我找到了合适的平衡点。在mvn package内,maven-archiver插件创建了target/maven-archiver/pom.properties并包含类似内容

version=0.0.1-SNAPSHOT
groupId=somegroup
artifactId=someArtifact

我正在使用bash来执行它

. ./target/maven-archiver/pom.properties

然后

echo $version
0.0.1-SNAPSHOT

当然,执行此文件绝对不安全,但是可以轻松地将执行转换为perl或bash脚本以从该文件读取和设置环境变量。

答案 18 :(得分:1)

Exec插件在没有任何输出解析的情况下工作,因为输出可以重定向到文件中并通过EnvInject插件注入作业环境:

enter image description here

答案 19 :(得分:0)

根据问题,我使用以下脚本自动增加所有maven父级/子模块中的版本号:

#!/usr/bin/env bash  

# Advances the last number of the given version string by one.  
function advance\_version () {  
    local v=$1  
    \# Get the last number. First remove any suffixes (such as '-SNAPSHOT').  
  local cleaned=\`echo $v | sed \-e 's/\[^0-9\]\[^0-9\]\*$//'\`  
 local last\_num=\`echo $cleaned | sed \-e 's/\[0-9\]\*\\.//g'\`  
 local next\_num=$(($last\_num+1))  
  \# Finally replace the last number in version string with the new one.  
  echo $v | sed \-e "s/\[0-9\]\[0-9\]\*\\(\[^0-9\]\*\\)$/$next\_num/"  
}  

version=$(mvn org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout)  

new\_version=$(advance\_version $version)  

mvn versions:set -DnewVersion=${new\_version} -DprocessAllModules -DgenerateBackupPoms=false

答案 20 :(得分:0)

一种选择是像这样用yq(https://github.com/kislyuk/yq)进行解析:

cat pom.xml | xq -r '.project.version'

请注意,可执行文件是xq而不是yq

要获取xq,请像这样pip install yq

安装yq

答案 21 :(得分:0)

在只有 busybox 可用的 docker 容器中,我使用 awk。

version=$(
 awk '
  /<dependenc/{exit}
  /<parent>/{parent++};
  /<version>/{
    if (parent == 1) {
      sub(/.*<version>/, "");
      sub(/<.*/, "");
      parent_version = $0;
    } else {
      sub(/.*<version>/, "");
      sub(/<.*/, "");
      version = $0;
      exit
    }
  }
  /<\/parent>/{parent--};
  END {
    print (version == "") ? parent_version : version
  }' pom.xml
)

注意事项:

  • 如果没有给出工件版本,则打印父版本。
  • 依赖项必须在工件和父版本之后。 (这可以很容易地克服,但我不需要它。)

答案 22 :(得分:0)

我在Travis工作期间确实需要此要求,但是有多个值。 我从this solution开始,但是在多次通话时,这非常慢(我需要5个表达式)。

我编写了一个简单的maven插件,将pom.xml的值提取到.sh文件中。

https://github.com/famaridon/ci-tools-maven-plugin

mvn com.famaridon:ci-tools-maven-plugin:0.0.1-SNAPSHOT:environment -Dexpressions=project.artifactId,project.version,project.groupId,project.build.sourceEncoding

会产生以下结果:

#!/usr/bin/env bash
CI_TOOLS_PROJECT_ARTIFACTID='ci-tools-maven-plugin';
CI_TOOLS_PROJECT_VERSION='0.0.1-SNAPSHOT';
CI_TOOLS_PROJECT_GROUPID='com.famaridon';
CI_TOOLS_PROJECT_BUILD_SOURCEENCODING='UTF-8';

现在您可以简单地获取文件

source .target/ci-tools-env.sh

玩得开心。

答案 23 :(得分:0)

将以下插件添加到您的 pom.xml

    ...
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-help-plugin</artifactId>
        <version>3.2.0</version>
        <executions>
            <execution>
                <id>generate-version-file</id>
                <phase>prepare-package</phase>
                <goals>
                    <goal>evaluate</goal>
                </goals>
                <configuration>
                    <expression>project.version</expression>
                    <output>${project.build.directory}/version.txt</output>
                </configuration>
            <execution>
        </executions>
    </plugin>
    ...

这将生成一个 target/version.txt 文件作为构建的正常部分。

然后你需要做的就是把它放到 shell 中:

#!/bin/sh
value=`cat target/version.txt`
echo "$value"
#!/bin/bash
value=$(<target/version.txt)
echo "$value"

答案 24 :(得分:0)

还有一种不需要Maven的选项:

grep -oPm1 "(?<=<version>)[^<]+" "pom.xml"

答案 25 :(得分:0)

要么mvn给你答案(正如大多数答案所示),要么你从pom.xml中提取答案。第二种方法的唯一缺点是,您可以非常轻松地提取<version/>标记的值,但只有当它是 literal 时才有意义,也就是说,它不是Maven属性。无论如何我选择了这种方法,因为:

  • mvn是详细的方式,我根本不喜欢过滤它的输出。
  • 与阅读mvn相比,开始pom.xml非常慢。
  • 我总是在<version/>中使用文字值。

mvn-version是一个zsh shell脚本,它使用xmlstarlet来读取pom.xml并打印项目版本(如果存在)或父版本项目(如果存在):

$ mvn-version .
1.0.0-SNAPSHOT

优势在于它比运行mvn更快方式

$ time mvn-version .
1.1.0-SNAPSHOT
mvn-version .  0.01s user 0.01s system 75% cpu 0.019 total

$ time mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate \
> -Dexpression=project.version
mvn org.apache.maven.plugins:maven-help-plugin:2.1.1:evaluate   4.17s user 0.21s system 240% cpu 1.823 total

我机器上的差异大于两个数量级。

答案 26 :(得分:0)

这对我有用,离线并且不依赖于mvn:

VERSION=$(grep --max-count=1 '<version>' <your_path>/pom.xml | awk -F '>' '{ print $2 }' | awk -F '<' '{ print $1 }')
echo $VERSION

答案 27 :(得分:-1)

这是上面的修改

  

cat pom.xml | grep“” |头-n 1 | sed -e“ s / version // g” |   sed -e“ s / \ s * [<> /] * // g”

我在cmdline上进行了测试,效果很好

grep“” pom.xml |头-n 1 | sed -e“ s / version // g” | sed -e“ s / \ s * [<> /] * // g”

是同一版本的另一个版本。我需要在未安装mvn的k8s中获取Jenkins CI中的版本号,所以这很有帮助

谢谢。

答案 28 :(得分:-1)

我在unix外壳中使用单线...

  

cat pom.xml | grep“” |头-n 1 | sed -e“ s / version // g” |   sed -e“ s / \ s * [<> /] * // g”

您可以将此行隐藏在Shell脚本中或作为别名。

答案 29 :(得分:-2)

VERSION=$(head -50 pom.xml | awk -F'>' '/SNAPSHOT/ {print $2}' | awk -F'<' '{print $1}')

这是我以前得到的版本号,以为会有更好的maven方式这样做

答案 30 :(得分:-2)

mvn help:evaluate -Dexpression=project.version | sed -e 1h -e '2,3{H;g}' -e '/\[INFO\] BUILD SUCCESS/ q' -e '1,2d' -e '{N;D}' | sed -e '1q'

我只是添加了我最近实现的小sed过滤器改进,以便从maven输出中提取project.version

答案 31 :(得分:-4)

Maven页脚很标准:

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.609s
[INFO] Finished at: Wed May 21 18:02:38 MSK 2014
[INFO] Final Memory: 17M/736M
[INFO] ------------------------------------------------------------------------

所以你可以使用以下代码:

> version=$(mvn help:evaluate -Dexpression=project.version | tail -8 | head -1)
> echo $version