这个简单的 BASH 脚本收集 PHP 项目中的 msgstr:
#!/bin/sh
TARGET=/path/to/project
LPATH=locale/cy_GB/LC_MESSAGES
POFILE=messages.po
mkdir -p $LPATH
touch $TARGET/$LPATH/$POFILE
cd $TARGET
find . -name '*.php' -print | xargs xgettext -j --from-code=UTF-8 -o $TARGET/$LPATH/$POFILE
我有两个问题:
为什么 -print 没有列出它找到的文件 - 所有文档都说它应该列出?
有没有办法指定 find 处理文件的顺序?如果我运行一个等效的 PHP 脚本,它会按照 ls 列出的顺序处理文件,然后进入目录。但是 find 似乎做了自己的事情,文件没有明显的顺序混乱,并且目录散布在其中?
答案1
find
与 bash 无关,它是一个单独的实用程序,如果您运行的是 Linux,则可能由 GNU findutils 在您的系统上提供。
-print
列出文件,但您不需要它——这是默认值。您可能没有“看到”它们的原因是因为它的输出是通过xargs
标准输入获取的——它永远不会到达您的终端。如果您希望它同时适用于两者,则需要使用tee
或类似的(请注意,如果您获得不受信任的文件名,您应该总是use -print0
,这里不包含它,因为它是一个不可移植的扩展):
find . -name '*.php' |
tee >(xargs xgettext -j --from-code=UTF-8 -o "$TARGET/$LPATH/$POFILE")
find
将按照找到文件的顺序打印文件,这是未排序的。如果你想让它们井然有序,你需要先跑sort
一遍。
答案2
find . -name '*.php' -print
打印文件名列表。这就是xargs
获取输入的地方。
为了避免文件名包含空格和其他特殊字符时出现令人讨厌的意外,请使用-print0
和xargs -0
find . -name '*.php' -print0 | xargs -0 xgettext -j --from-code=UTF-8 -o "$TARGET/$LPATH/$POFILE"
或使用该-exec
操作来代替:
find . -name '*.php' -exec xgettext -j --from-code=UTF-8 -o "$TARGET/$LPATH/$POFILE" {} +
注意,如果文件太多,xgettext
将会执行多次,每批文件执行一次。无论您使用xargs
或,都会如此-exec
。为了避免这种情况,由于您使用的是 bash,请使用其内置的递归目录遍历功能而不是find
.
shopt -s globstar
xgettext -j --from-code=UTF-8 -o "$TARGET/$LPATH/$POFILE" **/*.php
这样,如果连接的文件名超过命令行长度限制,您将收到错误而不是静默截断的文件。请注意,在 bash 中,**/
遍历目录的符号链接,而不仅仅是目录。如果出现问题,请使用 ksh 或 zsh 而不是 bash,或者使用其他方法。
使用 时find
,为了避免一次又一次无提示地覆盖输出文件,请写入标准输出并将整个find
命令重定向到文件。
find . -name '*.php' -exec xgettext -j --from-code=UTF-8 {} + >"$TARGET/$LPATH/$POFILE"
find
按照找到文件的顺序列出文件,它不进行任何排序。既不按名称排序,也不按其他文件之前或之后的目录排序。 (目录是文件。目录中没有单独的子目录和其他文件列表。)
find
始终在目录本身之后立即列出目录的内容。使用选项-depth
,情况会相反:首先是目录的内容,然后是目录本身。
答案3
如果您的目标目录没有任何子文件夹,您可以尝试使用*
展开所有以 结尾的文件.php
并使用xgettext
.这将消除对find
和 的需要xargs
。
for i in ./*.php; do
xgettext -j --from-code=UTF-8 -o $TARGET/$LPATH/$POFILE $i
done
如果您需要使用 进行递归搜索find
,您可以迭代包含命令的子 shell 的输出find
。
for i in $(find . -name '*.php'); do
xgettext -j --from-code=UTF-8 -o $TARGET/$LPATH/$POFILE $i
done