在特定目录中查找具有特定字符串的文件并替换

在特定目录中查找具有特定字符串的文件并替换

我有一个像这样的文件夹结构。

.
└── apps/
    ├── bo/
    │   └── platform/
    │       └── values-dev.yaml
    ├── canary/
    │   └── platform/
    │       └── values-canary-dev.yaml
    ├── foo/
    │   ├── customer
    │   ├── audit
    │   ├── platform/
    │   │   └── values-foo-dev.yaml
    │   └── platform-gb/
    │       └── values-foo-dev.yaml
    └── bar/
        ├── customer
        ├── audit
        ├── platform/
        │   └── values-bar-dev.yaml
        ├── platform-usa/
        │   └── values-bar-dev.yaml
        ├── platform-ca/
        │   └── values-bar-dev.yaml
        └── platform-ie/
            └── values-bar-dev.yaml

提前对措辞表示歉意。

我试图用来bash查找和替换puppy每个values-*-dev.yaml文件中存在的特定字符串我只想在每个子目录下foo以及bar每个子目录中存在的文件上更改它platform并替换dogdog

我得到的最接近的是下面的内容,它只列出了里面的文件foo,但我一生都无法弄清楚这一点。

find . -type f -path '*foo/platform*' -name 'values-*-dev.yaml'

我认为用foo括号括起来并添加bar它会起作用,但事实并非如此

find . -type f -path '*(foo|bar)/platform*' -name 'values-*-dev.yaml'

答案1

不,find's-name并且-path仅支持基本的 sh 通配符模式,因此仅适用于任意数量的字符的?单个字符以及范围/集/类中的单个字符(并转义这些字符)...*[...]\

在这里,使用标准find,你会做

find . '(' -path '*/foo/platform*' -o -path '*/bar/platform*' ')' \
       -name 'values-*-dev.yaml' \
       -type f \
        -exec perl -pi -e 's/puppy/dog/g' {} +

某些find实现还支持-regex谓词以使用正则表达式匹配完整路径。为了扩展regexps,在 BSD 上,您可以使用-E类似于 grep/sed 和 GNU 的选项find,即-regextype posix-extended“选项谓词”。

对于所有变体,正则表达式都是隐式锚定的,因此您需要:

# BSD
find -E . -regex '.*/(foo|bar)/platform.*' \
          -name 'values-*-dev.yaml' \
          -type f \
          -exec perl -pi -e 's/puppy/dog/g' {} +
# GNU
find . -regextype posix-extended \
       -regex '.*/(foo|bar)/platform.*' \
       -name 'values-*-dev.yaml' \
       -type f \
       -exec perl -pi -e 's/puppy/dog/g' {} +

或者你可以使用zsh,它就是:

perl -pi -e 's/puppy/dog/g' -- **/(foo|bar)/platform*/**/values-*-dev.yaml(.)

由于 zsh 在基本 sh 基础上有几个有用的 glob 模式扩展,包括:

  • **/匹配任何级别的子目录
  • (a|b): 与扩展正则表达式类似的交替。
  • glob 限定符包括.此处用于将搜索限制为常规的文件(相当于finds -type f)。

相关内容