在每个目录上编译 .proto 文件
Compile .proto files on every directory
我有这样的目录结构:
Makefile
README.md
go.mod
google/
-> Protobuf dependencies (ignore)
gopb/
-> Compiled Go protobuf files (ignore)
protoc-gen-openapiv2/
-> Protobuf OpenAPI depdencies (ignore)
providers/
- polygon/
- tickers.proto
- query.proto
我想设置一个命令,它可以找到所有包含 .proto
文件(上面指出的除外)和 运行 protoc 的目录,输出到gopb
目录下的同名目录。到目前为止,我已经能够创建一个 find
命令 returns 目录名称:
$ find -not \( -path "*.git*" -or -path "*google*" -or -path "*protoc*" -or -path . -or -path "*gopb*" \) -type d -print
./providers
./providers/polygon
显然,这并不完全准确,我想解决这个问题,但主要问题是,当我使用 -exec
标志调用协议时:
$ find -not \( -path "*.git*" -or -path "*google*" -or -path "*protoc*" -or -path . -or -path "*gopb*" \) -type d \
> -exec protoc --go_out=./gopb/ --go_opt=paths=source_relative {}/*.proto \;
这会打印出两个错误:
Could not make proto path relative: ./providers/*.proto: No such file or directory
Could not make proto path relative: ./providers/polygon/*.proto: No such file or directory
我不确定我在这里做错了什么,因为如果我调用 protoc --go_out=./gopb/ --go_opt=paths=source_relative ./providers/polygon/*.proto
,它会按预期创建文件。我在这里做错了什么?
有多种方法可以解决该问题,但要将 *.proto
视为一个 glob,您需要将其解释为 shell。
以下是使用 find
和 bash
的方法:
find . -not \( ...paths... \) \
-type d \
-exec bash -c '
shopt -s nullglob
for d
do
f=( "$d"/*.proto )
(( ${#f[@]} > 0 )) || continue
protoc --go_out=./gopb/ --go_opt=paths=source_relative "${f[@]}"
done
' _ {} +
在@Fravadona 的帮助下,我意识到我用来编译 .proto
文件的方法行不通。因此,我将所有要编译的 protobuf 文件移动到一个名为 protos
的新目录中,这将我的目录结构修改为:
Makefile
README.md
go.mod
google/
-> Protobuf dependencies (ignore)
gopb/
-> Compiled Go protobuf files (ignore)
protoc-gen-openapiv2/
-> Protobuf OpenAPI depdencies (ignore)
protos/
- providers/
- polygon/
- tickers.proto
- query.proto
然后我将命令修改为:
find ./protos -type f -name "*.proto" -exec protoc --go_out=../../../ {} \;
这个新命令在 /protos
目录中查找所有 .proto
文件并在每个文件上调用 protoc
。我删除了 source-relative 选项,这也需要在我的导入中进行一些代码更改。但是,这适合我的需要。请注意,我必须使用 ../../../
作为我的输出目录,因为我的 protobuf 存储库存在于 github.com/myrepo/protobuf
中,我希望将文件写入 github.com/myrepo/protobuf/gopb
.
我有这样的目录结构:
Makefile
README.md
go.mod
google/
-> Protobuf dependencies (ignore)
gopb/
-> Compiled Go protobuf files (ignore)
protoc-gen-openapiv2/
-> Protobuf OpenAPI depdencies (ignore)
providers/
- polygon/
- tickers.proto
- query.proto
我想设置一个命令,它可以找到所有包含 .proto
文件(上面指出的除外)和 运行 protoc 的目录,输出到gopb
目录下的同名目录。到目前为止,我已经能够创建一个 find
命令 returns 目录名称:
$ find -not \( -path "*.git*" -or -path "*google*" -or -path "*protoc*" -or -path . -or -path "*gopb*" \) -type d -print
./providers
./providers/polygon
显然,这并不完全准确,我想解决这个问题,但主要问题是,当我使用 -exec
标志调用协议时:
$ find -not \( -path "*.git*" -or -path "*google*" -or -path "*protoc*" -or -path . -or -path "*gopb*" \) -type d \
> -exec protoc --go_out=./gopb/ --go_opt=paths=source_relative {}/*.proto \;
这会打印出两个错误:
Could not make proto path relative: ./providers/*.proto: No such file or directory
Could not make proto path relative: ./providers/polygon/*.proto: No such file or directory
我不确定我在这里做错了什么,因为如果我调用 protoc --go_out=./gopb/ --go_opt=paths=source_relative ./providers/polygon/*.proto
,它会按预期创建文件。我在这里做错了什么?
有多种方法可以解决该问题,但要将 *.proto
视为一个 glob,您需要将其解释为 shell。
以下是使用 find
和 bash
的方法:
find . -not \( ...paths... \) \
-type d \
-exec bash -c '
shopt -s nullglob
for d
do
f=( "$d"/*.proto )
(( ${#f[@]} > 0 )) || continue
protoc --go_out=./gopb/ --go_opt=paths=source_relative "${f[@]}"
done
' _ {} +
在@Fravadona 的帮助下,我意识到我用来编译 .proto
文件的方法行不通。因此,我将所有要编译的 protobuf 文件移动到一个名为 protos
的新目录中,这将我的目录结构修改为:
Makefile
README.md
go.mod
google/
-> Protobuf dependencies (ignore)
gopb/
-> Compiled Go protobuf files (ignore)
protoc-gen-openapiv2/
-> Protobuf OpenAPI depdencies (ignore)
protos/
- providers/
- polygon/
- tickers.proto
- query.proto
然后我将命令修改为:
find ./protos -type f -name "*.proto" -exec protoc --go_out=../../../ {} \;
这个新命令在 /protos
目录中查找所有 .proto
文件并在每个文件上调用 protoc
。我删除了 source-relative 选项,这也需要在我的导入中进行一些代码更改。但是,这适合我的需要。请注意,我必须使用 ../../../
作为我的输出目录,因为我的 protobuf 存储库存在于 github.com/myrepo/protobuf
中,我希望将文件写入 github.com/myrepo/protobuf/gopb
.