我有这个:
find . -type f -name '*_test.go' | xargs dirname
但我得到:
用法:目录名路径
的输出
$ find . -type f -name '*_test.go'
是:
./pkg_test.go
./v3/organization/organization_test.go
./v3/common/pkg_test.go
./v3/model/boil_main_test.go
./v3/model/boil_queries_test.go
./v3/model/advances_test.go
./v3/model/boil_suites_test.go
./v3/model/psql_main_test.go
./v3/model/psql_suites_test.go
有人知道如何获取文件的目录名吗?也许我需要绝对路径?
答案1
三种方式:
首先,你的xargs
方法失败了,因为你dirname
一次给出了多个路径名。相反,将路径名一一传递给它:
find . -type f -name '*_test.go' -print0 | xargs -0 -r -I {} dirname {}
with-print0
和find
with-0
将xargs
路径名作为空分隔列表而不是换行分隔列表传递。-r
的选项将xargs
确保dirname
在没有来自 的输入时不会运行find
。
如果您知道您的文件名不包含嵌入的换行符:
find . -type f -name '*_test.go' | xargs -r -I {} dirname {}
其次,调用一个内联 shell 脚本,该脚本在文件上一一find
运行:dirname
find . -type f -name '*_test.go' -exec sh -c '
for pathname do
dirname "$pathname"
done' sh {} +
或者,不要调用dirname
,而是在循环中使用参数替换(更快):
find . -type f -name '*_test.go' -exec sh -c '
for pathname do
printf "%s\n" "${pathname%/*}"
done' sh {} +
第三,如果您使用 GNU find
,请使用它-printf
:
find . -type f -name '*_test.go' -printf '%h\n'
最后,如果您使用zsh
:
print -rC1 -- ./**/*_test.go(.ND:h)
glob修饰符(.ND:h)
要求之前的通配模式仅扩展到常规文件 ( .
),如果没有与该模式匹配的文件则扩展为空(N
,如nullglob
)bash
,并且还包含隐藏名称(D
,如dotglob
)bash
。最后:h
的 导致返回每个匹配路径名的“头”(即不带文件名的路径名的目录部分)。
bash
您可以在循环中执行等效操作,如下所示:
shopt -s globstar nullglob dotglob
for pathname in ./**/*_test.go; do
if [[ -f $pathname ]] && [[ ! -h $pathname ]]; then
printf '%s\n' "${pathname%/*}"
fi
done