使用 find 处理文件的顺序和打印

使用 find 处理文件的顺序和打印

这个简单的 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

我有两个问题:

  1. 为什么 -print 没有列出它找到的文件 - 所有文档都说它应该列出?

  2. 有没有办法指定 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获取输入的地方。

为了避免文件名包含空格和其他特殊字符时出现令人讨厌的意外,请使用-print0xargs -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

相关内容