简体   繁体   English

使用`find`查找pom.xml文件并进行Maven构建,忽略嵌套的POM

[英]Using `find` to find pom.xml file and do a maven build, ignoring nested POMs

I currently have a couple of applications with different folder structures. 我目前有几个具有不同文件夹结构的应用程序。 I am using maven for building these apps. 我正在使用maven来构建这些应用程序。 I am running into some issues. 我遇到了一些问题。 At times the main pom.xml file is in the root directory and other times it is in the sub-directory. 有时主pom.xml文件位于根目录中,而其他时候则位于子目录中。 I only want to do a maven build with the main pom.xml found in the main/highest directory. 我只想使用在main / highest目录中找到的主要pom.xml进行Maven构建。 I am running the find command from workspace (below for more details). 我正在从workspace运行find命令(有关更多详细信息,请参见下文)。 How could I achieve this without depending on the folder structure? 在不依赖文件夹结构的情况下如何实现?

Shell Command: Shell命令:

find * -maxdepth 1 -name pom.xml -execdir mvn clean package -Dmaven.test.error.ignore=true -Dmaven.test.failure.ignore=true \;

This works with this folder structure: 这适用于以下文件夹结构:

workspace
|-- app1
|   |-- pom.xml
|   |-- abrt.conf
|   |-- gpg_keys
|   `-- web
|       |-- pom.xml
|       `-- test.conf

returns: 收益:

app1/pom.xml

The command does returns a couple of pom.xml files with this folder structure: 该命令确实返回了几个具有以下文件夹结构的pom.xml文件:

workspace
|   |-- pom.xml
|   |-- abrt.conf
|   |-- gpg_keys
|   `-- web
|       |-- pom.xml
|       `-- test.conf

returns: 收益:

web/pom.xml
pom.xml

Because find operates breadth-first unless explicitly told to do otherwise, the first result will always be the shallowest. 因为除非明确要求否则find操作是广度优先的,所以第一个结果将始终是最浅的。 Thus, you just need to tell it to quit after finding a single POM file. 因此,您只需要在找到单个POM文件后告诉它退出即可。

In GNU find , there's a -quit action for exactly this purpose: 在GNU find ,有一个-quit操作正是出于这个目的:

find . -name pom.xml \
  -execdir mvn clean package -Dmaven.test.error.ignore=true -Dmaven.test.failure.ignore=true \; \
  -quit

If you aren't guaranteed to have GNU find , but are guaranteed to have bash, you can read just the first result and operate on that: 如果不能保证可以使用GNU find ,但是可以保证可以使用bash,则可以只读取第一个结果并对其进行操作:

if IFS= read -r -d '' pom_filename < <(find . -name pom.xml -print0); then
  (cd -- "${pom_filename%/*}" && exec mvn clean package -Dmaven.test.error.ignore=true -Dmaven.test.failure.ignore=true)
fi

Note the use of -print0 -- that way we avoid maliciously-named directories (with newlines) being able to influence behavior by injecting extra names into the list. 请注意-print0的使用-这样我们可以避免通过将多余的名称注入列表来避免使用恶意名称的目录(使用换行符)来影响行为。


Now, let's consider a trickier case: 现在,让我们考虑一个更棘手的情况:

A/pom.xml
A/sub/pom.xml
B/pom.xml
B/sub/pom.xml

If you want to run for both A and B, but not A/sub or B/sub, then things get a bit more interesting: 如果您想为A和B 跑,但不是A /分或B /次,然后事情就变得更有趣:

find . \
    -type d -exec test -e '{}/pom.xml' ';' \
    -execdir mvn clean pkg ... ';' \
    -prune

Note that we're using -prune to tell find to stop recursing into any directory where a pom.xml exists, but only after we already ran a build there. 请注意,我们正在使用-prune告诉find停止递归到pom.xml存在的任何目录,但pom.xml是我们已经在其中运行了构建。

Just do a find without the * (replace with . as suggested in comment) to list from highest directory to the lowest. 只需find不带* (按注释中的.替换)即可从最高目录到最低目录列出。 Pipe to head -1 to get the first one of the list. 移至head -1可获得列表中的第一个。 Put all of this into a command substitution ( $(...) ) to assign a variable. 将所有这些都放入命令替换( $(...) )中以分配变量。 Run the same command with your variable instead. 而是使用变量运行相同的命令。 Since you may have / in the file name now, we will not need -name , -maxdepth or * . 由于您现在的文件名中可能带有/ ,因此我们不需要-name-maxdepth*

pomxmlfile="$(find . -name pom.xml | head -1)"
find "$pomxmlfile" -execdir mvn clean package -Dmaven.test.error.ignore=true -Dmaven.test.failure.ignore=true \;

This line finds the pom.xml with the shortest path (ie the pom nearest the top of the directory tree) and executes mvn from its directory: 这一行找到路径最短的pom.xml (即最靠近目录树顶部的pom),并从其目录执行mvn

find . -name pom.xml | awk '{print length($0) " " $0}' | sort -n | cut -d ' ' -f 2- | head -n 1 | xargs -I {} bash -c 'cd $(dirname {}) && mvn clean package -Dmaven.test.error.ignore=true -Dmaven.test.failure.ignore=true \;'

Pipe chain breakdown: 管链故障:

  • finds all pom.xml under current directory 在当前目录下找到所有pom.xml
  • adds length of line to start of line 将行长添加到行首
  • sorts lines by number (ie the length) lowest first 按数字(即长度)从低到低排序
  • removes the length 去除长度
  • keeps only the first (ie shortest) line 仅保留第一行(即最短)
  • runs mvn from the directory of the pom.xml file pom.xml文件的目录运行mvn

I'm not sure. 我不确定。 If the main pom.xml is in a directory a/b/c and no other pom.xml is in a subdirectory below a other than a/b/c , then the main pom.xml must have the shortest path string. 如果主pom.xml是目录中的a/b/c并没有其他pom.xml是在下边的子目录a比其他a/b/c ,那么主要pom.xml必须的最短路径字符串。 So in that case I guess this command brings up the pom.xml closest to root and can be executed from either a , a/b , or a/b/c : 因此,在那种情况下,我猜想此命令将调出最接近root的pom.xml ,并且可以从aa/ba/b/c

find -name pom.xml | awk 'NR==1 || length() < length(s) { s = $0 } END { print s }'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM