답변:
프로젝트에 포함되어 있지 않지만 폴더에있는 파일의 경우
cmd ⌘+ alt ⌥+A
회색으로 표시되지 않습니다.
xib 또는 코드에서 참조되지 않는 파일의 경우 다음과 같이 작동 할 수 있습니다.
#!/bin/sh
PROJ=`find . -name '*.xib' -o -name '*.[mh]'`
find . -iname '*.png' | while read png
do
name=`basename $png`
if ! grep -qhs "$name" "$PROJ"; then
echo "$png is not referenced"
fi
done
이보다 강력한 솔루션입니다 - 그것은으로 확인 모든 텍스트 파일의 기본 이름을 참조. 스토리 보드 파일을 포함하지 않은 위의 솔루션에 유의하십시오 (완전히 이해할 수 있지만 당시에는 존재하지 않았습니다).
Ack는 이것을 매우 빠르게 만들지 만,이 스크립트가 자주 실행된다면 몇 가지 명백한 최적화가 있습니다. 예를 들어이 코드는 retina / non-retina 자산이 모두있는 경우 모든 기본 이름을 두 번 확인합니다.
#!/bin/bash
for i in `find . -name "*.png" -o -name "*.jpg"`; do
file=`basename -s .jpg "$i" | xargs basename -s .png | xargs basename -s @2x`
result=`ack -i "$file"`
if [ -z "$result" ]; then
echo "$i"
fi
done
# Ex: to remove from git
# for i in `./script/unused_images.sh`; do git rm "$i"; done
chmod a+x FindUnusedImages.sh
), 다음 떠들썩한 파티에서 다른 프로그램처럼 실행./FindUnusedImages.sh
result=`ack --ignore-file=match:/.\.pbxproj/ -i "$file"`
이것은 ack 2.0 이상이 필요합니다
LSUnusedResources를 사용해보십시오 .
jeffhodnett의 Unused에 크게 영향을 받지만 솔직히 Unused는 매우 느리고 결과가 완전히 정확하지는 않습니다. 그래서 성능을 최적화했습니다. 검색 속도가 미사용보다 빠릅니다.
나는 Roman의 솔루션을 시도하고 망막 이미지를 처리하기 위해 몇 가지 조정을 추가했습니다. 잘 작동하지만 이미지 이름은 코드에서 프로그래밍 방식으로 생성 될 수 있으며이 스크립트는 이러한 이미지를 참조되지 않은 것으로 잘못 나열합니다. 예를 들어,
NSString *imageName = [NSString stringWithFormat:@"image_%d.png", 1];
이 스크립트 image_1.png
는 참조되지 않은 것으로 잘못 인식 합니다.
수정 된 스크립트는 다음과 같습니다.
#!/bin/sh
PROJ=`find . -name '*.xib' -o -name '*.[mh]' -o -name '*.storyboard' -o -name '*.mm'`
for png in `find . -name '*.png'`
do
name=`basename -s .png $png`
name=`basename -s @2x $name`
if ! grep -qhs "$name" "$PROJ"; then
echo "$png"
fi
done
이 스크립트만이 파일 이름의 공간을 처리하는 나를 위해 작동합니다.
지원에 업데이트 swift
파일과 cocoapod
. 기본적으로 Pod 디렉터리를 제외하고 프로젝트 파일 만 확인합니다. 실행하여 Pods 폴더도 확인하려면 --pod
attrbiute로 실행 하십시오.
/.finunusedimages.sh --pod
실제 스크립트는 다음과 같습니다.
#!/bin/sh
#varables
baseCmd="find ."
attrs="-name '*.xib' -o -name '*.[mh]' -o -name '*.storyboard' -o -name '*.mm' -o -name '*.swift'"
excudePodFiles="-not \( -path */Pods/* -prune \)"
imgPathes="find . -iname '*.png' -print0"
#finalize commands
if [ "$1" != "--pod" ]; then
echo "Pod files excluded"
attrs="$excudePodFiles $attrs"
imgPathes="find . $excudePodFiles -iname '*.png' -print0"
fi
#select project files to check
projFiles=`eval "$baseCmd $attrs"`
echo "Looking for in files: $projFiles"
#check images
eval "$imgPathes" | while read -d $'\0' png
do
name=`basename -s .png "$png"`
name=`basename -s @2x $name`
name=`basename -s @3x $name`
if grep -qhs "$name" $projFiles; then
echo "(used - $png)"
else
echo "!!!UNUSED - $png"
fi
done
자산 카탈로그를 활용하는 프로젝트를 처리하기 위해 @EdMcManus가 제공 한 훌륭한 답변을 약간 수정했습니다.
#!/bin/bash
for i in `find . -name "*.imageset"`; do
file=`basename -s .imageset "$i"`
result=`ack -i "$file" --ignore-dir="*.xcassets"`
if [ -z "$result" ]; then
echo "$i"
fi
done
나는 실제로 bash 스크립트를 작성하지 않으므로 여기에서 개선해야 할 사항이 있으면 (아마도) 의견으로 알려 주시면 업데이트하겠습니다.
루아 스크립트를 작성했는데 직장에서했기 때문에 공유 할 수 있을지 모르겠지만 잘 작동합니다. 기본적으로 다음을 수행합니다.
1 단계-정적 이미지 참조 (다른 답변에서 다루는 쉬운 부분)
2 단계-동적 이미지 참조 (재미있는 부분)
그런 다음 두 검색에서 찾지 못한 모든 것을 삭제합니다.
가장 중요한 경우는 서버에서 가져온 이미지 이름이 처리되지 않는다는 것입니다. 이를 처리하기 위해이 검색에 서버 코드를 포함합니다.
Xcode 용 FauxPas 앱을 사용해 볼 수 있습니다 . Xcode 프로젝트와 관련된 누락 된 이미지 및 기타 많은 문제 / 위반을 찾는 데 정말 좋습니다.
다른 답변을 사용하면 이것은 두 디렉토리의 이미지를 무시하고 pbxproj 또는 xcassets 파일에서 이미지 발생을 검색하지 않는 방법에 대한 좋은 예입니다 (앱 아이콘 및 스플래시 화면에주의하십시오). --ignore-dir = *. xcassets에서 *를 디렉토리와 일치하도록 변경합니다.
#!/bin/bash
for i in `find . -not \( -path ./Frameworks -prune \) -not \( -path ./Carthage -prune \) -not \( -path ./Pods -prune \) -name "*.png" -o -name "*.jpg"`; do
file=`basename -s .jpg "$i" | xargs basename -s .png | xargs basename -s @2x | xargs basename -s @3x`
result=`ack -i --ignore-file=ext:pbxproj --ignore-dir=*.xcassets "$file"`
if [ -z "$result" ]; then
echo "$i"
fi
done
이 프레임 워크를 사용했습니다.
http://jeffhodnett.github.io/Unused/
잘 작동합니다! 내가 문제를 본 두 곳은 이미지 이름이 서버에서 왔고 이미지 자산 이름이 자산 폴더 내의 이미지 이름과 다른 경우입니다.
http://jeffhodnett.github.io/Unused/ 를 사용 하여 사용하지 않는 이미지를 찾으십시오.
사용하지 않는 이미지를 식별하기 위해 파이썬 스크립트를 만들었습니다 : 'unused_assets.py'@ gist . 다음과 같이 사용할 수 있습니다.
python3 unused_assets.py '/Users/DevK/MyProject' '/Users/DevK/MyProject/MyProject/Assets/Assets.xcassets'
다음은 스크립트를 사용하는 몇 가지 규칙입니다.
첫 번째 버전의 제한 사항 :
피드백을 기반으로 시간이 지남에 따라 개선하려고 노력할 것이지만 첫 번째 버전이 대부분에게 좋습니다.
코드 아래에서 찾으십시오. 각 중요한 단계에 적절한 주석을 추가 했으므로 코드는 자명해야합니다 .
# Usage e.g.: python3 unused_assets.py '/Users/DevK/MyProject' '/Users/DevK/MyProject/MyProject/Assets/Assets.xcassets'
# It is important to pass project folder path as first argument, assets folder path as second argument
# It is assumed that all the images are maintained within Assets.xcassets folder and are used either within swift files or within storyboards
"""
@author = "Devarshi Kulshreshtha"
@copyright = "Copyright 2020, Devarshi Kulshreshtha"
@license = "GPL"
@version = "1.0.1"
@contact = "kulshreshtha.devarshi@gmail.com"
"""
import sys
import glob
from pathlib import Path
import mmap
import os
import time
# obtain start time
start = time.time()
arguments = sys.argv
# pass project folder path as argument 1
projectFolderPath = arguments[1].replace("\\", "") # replacing backslash with space
# pass assets folder path as argument 2
assetsPath = arguments[2].replace("\\", "") # replacing backslash with space
print(f"assetsPath: {assetsPath}")
print(f"projectFolderPath: {projectFolderPath}")
# obtain all assets / images
# obtain paths for all assets
assetsSearchablePath = assetsPath + '/**/*.imageset' #alternate way to append: fr"{assetsPath}/**/*.imageset"
print(f"assetsSearchablePath: {assetsSearchablePath}")
imagesNameCountDict = {} # empty dict to store image name as key and occurrence count
for imagesetPath in glob.glob(assetsSearchablePath, recursive=True):
# storing the image name as encoded so that we save some time later during string search in file
encodedImageName = str.encode(Path(imagesetPath).stem)
# initializing occurrence count as 0
imagesNameCountDict[encodedImageName] = 0
print("Names of all assets obtained")
# search images in swift files
# obtain paths for all swift files
swiftFilesSearchablePath = projectFolderPath + '/**/*.swift' #alternate way to append: fr"{projectFolderPath}/**/*.swift"
print(f"swiftFilesSearchablePath: {swiftFilesSearchablePath}")
for swiftFilePath in glob.glob(swiftFilesSearchablePath, recursive=True):
with open(swiftFilePath, 'rb', 0) as file, \
mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_READ) as s:
# search all the assests within the swift file
for encodedImageName in imagesNameCountDict:
# file search
if s.find(encodedImageName) != -1:
# updating occurrence count, if found
imagesNameCountDict[encodedImageName] += 1
print("Images searched in all swift files!")
# search images in storyboards
# obtain path for all storyboards
storyboardsSearchablePath = projectFolderPath + '/**/*.storyboard' #alternate way to append: fr"{projectFolderPath}/**/*.storyboard"
print(f"storyboardsSearchablePath: {storyboardsSearchablePath}")
for storyboardPath in glob.glob(storyboardsSearchablePath, recursive=True):
with open(storyboardPath, 'rb', 0) as file, \
mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_READ) as s:
# search all the assests within the storyboard file
for encodedImageName in imagesNameCountDict:
# file search
if s.find(encodedImageName) != -1:
# updating occurrence count, if found
imagesNameCountDict[encodedImageName] += 1
print("Images searched in all storyboard files!")
print("Here is the list of unused assets:")
# printing all image names, for which occurrence count is 0
print('\n'.join({encodedImageName.decode("utf-8", "strict") for encodedImageName, occurrenceCount in imagesNameCountDict.items() if occurrenceCount == 0}))
print(f"Done in {time.time() - start} seconds!")