三点通配符

use*_*313 5 shell directory recursive file-copy wildcards

我有一个非常大的源代码目录结构,很难使用。我想运行一个工具将其转换为对我更有效的类似 Maven 的结构。当我完成我的工作时,我再次运行该工具将 Maven 结构转换回原来的糟糕结构。我非常熟悉各种 shell,是的,我可以编写一个包含数百个 cp 命令的脚本。但这将很难维持。

我希望能够使用 Perforce 的三点通配符之类的东西来移动或复制文件:

匹配当前工作目录和所有子目录下的所有文件。(匹配任何内容,包括斜杠,并且跨子目录匹配)

我的脚本将包含如下命令:

cp src/.../foobar/.../*.java trusted/src/main/java/.../foobar/.../*.java
Run Code Online (Sandbox Code Playgroud)

这个想法是移动目录的子树,同时保持该子树的结构。

有任何想法吗?

我在使用 Gilles 的 rsync 解决方案时遇到问题。这是一个测试脚本:

#!/bin/bash

rm -rf source

mkdir -p source/server/src/com/bodhi/foobar/this
mkdir -p source/server/src/com/bodhi/foobar/that
mkdir -p source/server/src/com/bodhi/other

echo "Hello World" > source/server/src/com/bodhi/foobar/this/A.java
echo "Hello World" > source/server/src/com/bodhi/foobar/that/B.java
echo "Hello World" > source/server/src/com/bodhi/other/C.java

rm -rf target
mkdir -p target/foobar/src/main/java

rsync \
  --include='**/foobar/**/*.java' \
  --include='**/foobar/**/' \
  --exclude='*' \
  --prune-empty-dirs \
  source/server/src/ target/foobar/src/main/java/
Run Code Online (Sandbox Code Playgroud)

Gil*_*il' 6

此通配符存在于 ksh93、bash ?4.3(如果树中没有指向目录的符号链接,则为 ?4.0)和 zsh。它的拼写**。在 ksh93 中,需要先用set -o globstar. 在 bash 中,需要先用shopt -o globstar.

ls -l src/**/foobar/**/*.java
Run Code Online (Sandbox Code Playgroud)

但是,这不会复制副本。的目标cp是单个目录,cp不做任何通配符匹配。您不能使用单个cp命令将文件放置在不同的位置。

您可以改用rsync。将源树的根和目标树的根传递给它,并定义包含和排除规则以仅复制您想要的文件和通向它们的目录。如果它们与模式匹配,Rsync 也会复制空目录,您可以使用--prune-empty-dirs.

rsync --include='**/foobar/**/*.java' --include='**/' \
      --exclude='*' --prune-empty-dirs \
      src/ trusted/src/main/java/
Run Code Online (Sandbox Code Playgroud)

您可以使用的另一个工具是pax。请注意,pax 是标准的,因为它是由 POSIX 定义的(与 rsync 不同),但是一些 Linux 发行版在默认安装中省略了它(但是它始终作为一个包提供)。方法类似于rsync:包含.java文件,排除其余文件;语法有点奇怪:您指定一个模式替换,它可以是包含文件的原始替换而不是重命名它,或者是一个空替换以排除文件。必要时会在目标中自动创建前导目录。

pax -rw -s '/\.java$/&/' -s '/.*//' src/* trusted/src/main/java/
Run Code Online (Sandbox Code Playgroud)