在 Xcode 工作区中查找未引用的 png 文件

Find unreferenced png files in an Xcode workspace

我有一个包含数百个 png 文件的 Xcode 工作区,我想列出那些未被引用的文件。

示例 png:

capture-bg-1.png
capture-bg-1@2x.png
promo_icon.png
promo_icon@2x.png

"promo_icon"(XML 文件)的参考示例:

<string>promo_icon</string>

"promo_icon"(Objective-C)的参考示例:

[UIImage imageNamed:@"promo_icon"]

我想获取包括 "capture-bg-1" 在内的文件名列表(假设它没有像 "promo_icon" 那样的匹配项)。

一个小问题是有一个 .pbxproj 文件 (XML) 引用了工作区中的每个 png 文件,因此需要从搜索中排除该文件。

以下命令获取所有唯一的文件名部分(不包括文件夹和“@”和“.”之后的所有内容)以进行评估。

find . -name *.png -exec basename {} \;| sed 's/[.@].*$//' | uniq

问题出在我将文件名部分传送到其中的 grep 部分。此 grep 查找引用或未引用 'promo_icon' 的文件并列出引用。一个空的 return 值(无引用)将是一个 png 文件我正在寻找以下列表:

grep -I -R promo_icon . | grep -v pbxproj

但是我不知道如何以实用的方式将两者结合起来。在 sh 中有用于执行此操作的代码段 (),但它不起作用。

一种更简单的方法可能是将所有 PNG 名称的列表放入一个文件中,每行一个。然后将所有对 PNG 名称的引用列表放入另一个文件中,每行一个。然后 grep -v -f 第一个文件对第二个。返回什么就是你的答案。

首先,

find . -name '*.png' -printf %f | sed -e 's/[.@].*$//' | sort -u > pngList

然后,

grep -RI --exclude .pbxproj -e '<string>.*png</string>' \
                            -e 'UIImage imageNamed' . > pngRefs

最后,

grep -v -f pngList pngRefs

您可以从那里用 sedsort -u 清理结果。

::编辑::

如果您有任何 PNG 的名称是其他 PNG 的适当子字符串,上述方法可能会产生一些错误的答案。例如,如果您有 promo_iconcheese_promo_icon 并且 promo_icon 从未被引用,但 cheese_promo_icon 引用,上述方法将不会检测到 promo_icon 未被引用。

要解决这个问题,您可以用 \b(字边界)序列包围您的 PNG 名称模式:

find . -name '*.png' -printf %f | sed -e 's/^/\b/' -e 's/$/\b/' -e 's/[.@].*$//' | sort -u > pngList

这样你的 pngList 文件将包含这样的行:

\bpromo_icon\b
\bcapture-bg-1\b

因此,当您 grep 它针对引用列表时,它只会在每个 PNG 的名称是图像引用中的完整名称(而不是较长名称的子字符串)时匹配。

这是在 Xcode 项目中查找未引用图像的脚本。一个陷阱是人们可能会使用字符串格式来构造对图像的引用,这在这里没有说明。 Mac 用户将希望通过 brew 安装 findutils 以获得带有 printf:

find 版本
#!/bin/sh
# Finds unreferenced PNG assets in an xcode project

# Get a list of png file stems, stripping out folder information, 'png' extension
# and '@2x' parts of the filename
for png in `find . -name '*.png' -printf '%f\n' | sed -e 's/[.@].*$//' | sort -u`

# Loop through the files and print out a list of files not referenced.  Keep in mind
# that some files like 'asset-1' may be referred to in code like 'asset-%d' so be careful
do
    name=`basename $png`
    if ! grep -qRI --exclude project.pbxproj --exclude-dir Podfile $png . ; then
        echo "$png is not referenced"
    fi
done