我有一个像这样的文件夹结构。
.
└── 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
并替换dog
为dog
我得到的最接近的是下面的内容,它只列出了里面的文件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 限定符包括
.
此处用于将搜索限制为常规的文件(相当于find
s-type f
)。