Xcode प्रोजेक्ट में अप्रयुक्त छवियों को कैसे खोजें?


97

क्या किसी के पास एक एक्सकोड परियोजना में अप्रयुक्त छवियों को खोजने के लिए एक-लाइन है? (सभी फाइलों को कोड या प्रोजेक्ट फाइलों में नाम से संदर्भित किया जाता है - कोई कोड उत्पन्न फ़ाइल नाम नहीं।)

ये फाइलें एक परियोजना के जीवन का निर्माण करती हैं और यह बताने में मुश्किल हो सकती है कि किसी भी दिए गए png को हटाना सुरक्षित है या नहीं।


4
क्या यह XCode4 के लिए भी काम करता है? XCode4 में Cmd-Opt-A को "फाइलें जोड़ें" डायलॉग खोलने लगता है।
राजवन्य सुब्रमण्यन ३०'१३

जवाबों:


61

उन फ़ाइलों के लिए, जो प्रोजेक्ट में शामिल नहीं हैं, लेकिन फ़ोल्डर में बस लटका हुआ है, आप दबा सकते हैं

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

6
यदि आप त्रुटि का सामना करते हैं: ऐसी कोई फ़ाइल या निर्देशिका नहीं है, तो यह संभवतः फ़ाइल पथ में रिक्त स्थान के कारण है। उद्धरण को grep लाइन में जोड़ने की आवश्यकता है, इसलिए यह जाता है: यदि! grep -qhs "$ name" "$ PROJ";
लुकाज़

8
एक परिदृश्य जहां यह काम नहीं करेगा जब हम उनके नाम के निर्माण के बाद छवियों को प्रोग्राम लोड कर सकते हैं। जैसे arm1.png, arm2.png .... arm22.png। मैं लूप और लोड के लिए उनके नाम का निर्माण कर सकता हूं। उदा गेम्स
राजवन सुब्रमण्यन

यदि आपके पास @ 2x के साथ रेटिना डिस्प्ले के लिए चित्र हैं तो वे अप्रयुक्त के रूप में सूचीबद्ध करेंगे। आप एक अतिरिक्त if-statement जोड़कर इससे छुटकारा पा सकते हैं: यदि [["$ नाम"! = @ 2x ]]; उसके बाद
स्टेन

3
Cmd + Opt + XCode 5 पर काम करने के लिए अब नहीं लगता है। इसे क्या ट्रिगर करना चाहिए?
पौव्वक

cmd + opt + किसी भी फाइल को ग्रे आउट करने के लिए प्रतीत नहीं होता है। भले ही वे प्रोजेक्ट का हिस्सा हों :(
tettoffensive

80

यह एक अधिक मजबूत समाधान है - यह किसी भी पाठ फ़ाइल में बेसन के संदर्भ के लिए जाँच करता है । ऊपर दिए गए समाधानों पर ध्यान दें जिसमें स्टोरीबोर्ड फाइलें शामिल नहीं थीं (पूरी तरह से समझने योग्य, वे उस समय मौजूद नहीं थे)।

Ack इसे बहुत तेज़ बनाता है, लेकिन यह स्पष्ट करने के लिए कुछ स्पष्ट अनुकूलन हैं कि क्या यह स्क्रिप्ट अक्सर चलती है। उदाहरण के लिए, यदि आपके पास रेटिना / गैर-रेटिना संपत्ति दोनों हैं, तो यह कोड हर बेसनेम की दो बार जांच करता है।

#!/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

12
Homebrew स्थापित करें और फिर एक करें brew install ack
मार्को

1
धन्यवाद। यह उत्तर सही ढंग से रिक्त स्थान के साथ फ़ाइलों और फ़ोल्डरों को भी संभालता है।
डीजेस्किनर

2
@ जॉनी आपको फ़ाइल को निष्पादन योग्य बनाने की आवश्यकता है ( chmod a+x FindUnusedImages.sh), फिर इसे बैश से किसी अन्य प्रोग्राम की तरह चलाएं./FindUnusedImages.sh
माइक स्प्रैग

2
मैंने pbxproj फ़ाइलों को अनदेखा करने के लिए एक संशोधन किया है (इस प्रकार उन फ़ाइलों को अनदेखा कर रहा हूं जो कि xcode प्रोजेक्ट में हैं, लेकिन कोड या nibs / स्टोरीबोर्ड में उपयोग नहीं किए गए हैं): result=`ack --ignore-file=match:/.\.pbxproj/ -i "$file"` इसके लिए ack 2.0 और up
माइक Sprague

2
मिलनपंचल, आप स्क्रिप्ट को कहीं भी रख सकते हैं, और आप छवियों को खोजने के लिए रूट के रूप में जो भी उपयोग करना चाहते हैं, उसी से इसे निष्पादित कर सकते हैं (जैसे आपका प्रोजेक्ट रूट फ़ोल्डर)। आप इसे ~ / स्क्रिप्ट / उदाहरण के लिए रख सकते हैं और फिर अपने प्रोजेक्ट रूट फ़ोल्डर में जा सकते हैं और इसे स्क्रिप्ट को सीधे इंगित करके चला सकते हैं: ~ / script / unused_images.sh
एरिक वैन डेर न्यूट

25

कृपया एक कोशिश LSUnusedResources है

यह jeffhodnett के अप्रयुक्त से बहुत प्रभावित है , लेकिन ईमानदारी से अप्रयुक्त बहुत धीमा है, और परिणाम पूरी तरह से सही नहीं हैं। इसलिए मैंने कुछ प्रदर्शन अनुकूलन किए, अप्रयुक्त की तुलना में खोज की गति अधिक तेज़ है।


2
वाह कि एक महान उपकरण है! उन लिपियों को चलाने की कोशिश करने की तुलना में बहुत अच्छा है। आप नेत्रहीन उन सभी छवियों को देख सकते हैं जिनका उपयोग नहीं किया गया है, और जिन्हें आप चाहते हैं उन्हें हटा दें। एक गोटा मुझे मिला, हालांकि यह है कि यह
प्लिस्ट

1
निश्चित रूप से भयानक और मेरा दिन बचाओ! धागे में सबसे अच्छा समाधान। आपने धमाल मचाया।
जेकाहो

2
धागे में सबसे अच्छा। काश यह अधिक होता और मैं एक से अधिक बार मतदान कर सकता था!
योव श्वार्ट्ज

क्या आप जानते हैं कि ऐसा ही कुछ है लेकिन मृत कोड का पता लगाने के लिए? उदाहरण के लिए, विधियों के लिए जिसे अब नहीं कहा जाता है (कम से कम अब सांख्यिकीय रूप से नहीं कहा जाता है )।
सुपरपुकियो

24

मैंने रोमन के समाधान की कोशिश की, और मैंने रेटिना छवियों को संभालने के लिए कुछ ट्वीक्स जोड़े। यह अच्छी तरह से काम करता है, लेकिन याद रखें कि छवि के नाम कोड में प्रोग्रामेटिक रूप से उत्पन्न हो सकते हैं, और यह स्क्रिप्ट गलत तरीके से इन छवियों को अप्रतिबंधित के रूप में सूचीबद्ध करेगी। उदाहरण के लिए, आपके पास हो सकता है

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

बेसन के लिए प्रत्यय स्विच में @ 2x क्या करता है ?
ThaDon

3
FYI करें, नाम के रिक्त स्थान वाले फ़ोल्डर स्क्रिप्ट के साथ समस्याएँ पैदा करते हैं।
स्टीव

3
यदि आप त्रुटि का सामना करते हैं: ऐसी कोई फ़ाइल या निर्देशिका नहीं है, तो यह संभवतः फ़ाइल पथ में रिक्त स्थान के कारण है। उद्धरण को grep लाइन में जोड़ने की आवश्यकता है, इसलिए यह जाता है: यदि! grep -qhs "$ name" "$ PROJ";
लुकाज़

3
यह स्क्रिप्ट मेरी सभी फाइलों को सूचीबद्ध करती है
jjxtra

2
मुझे पता नहीं क्यों यह मेरे लिए काम नहीं कर रहा है, मुझे इसकी सभी पीएनजी छवियां दे रहा है
ओमर ओबैद

12

हो सकता है कि आप पतला होने की कोशिश कर सकते हैं , एक अच्छा काम करता है।

अद्यतन: इमकेनस विचार के साथ, मैं आगे बढ़ गया और बिना किसी मशीन के अतिरिक्त सेटअप से बचने के लिए बिना किसी ऐक के साथ एक छोटा सा उपयोग करना।

https://github.com/arun80/xcodeutils


1
पतला भुगतान किया गया ऐप है। कई झूठे सकारात्मक और वाणिज्यिक उत्पादों के लिए अच्छा नहीं है। इमकेमेनस द्वारा प्रदान की गई स्क्रिप्ट वास्तव में बहुत अच्छी है।
अरुण

6

केवल यह स्क्रिप्ट मेरे लिए काम कर रही है, जो फिल्म के नाम में जगह भी संभाल रही है:

संपादित करें

swiftफ़ाइलों का समर्थन करने के लिए अद्यतन और cocoapod। डिफ़ॉल्ट रूप से यह पॉड्स डाइर को छोड़कर केवल प्रोजेक्ट फाइलों की जांच करता है। पॉड्स फ़ोल्डर की जाँच करने के लिए चलाने के लिए, --podअट्रिब्यूट के साथ चलाएँ:

/.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

इस लिपि ने बहुत से उपयोग किए गए संसाधनों को अप्रयुक्त के रूप में चिह्नित किया है । सुधार की जरूरत है।
आर्टेम शमाटकोव

इसके अलावा बड़ी, गहरी परियोजना पदानुक्रम पसंद नहीं है: ./findunused.sh: पंक्ति 28: / usr / बिन / grep: तर्क सूची बहुत लंबी है
मार्टिन-गाइल्स लावोई

3

मैंने संपत्ति कैटलॉग का उपयोग करने वाली परियोजनाओं को संभालने के लिए @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

मैं वास्तव में बैश स्क्रिप्ट नहीं लिखता हूं, इसलिए यदि यहां सुधार किए जाने हैं (संभावना है) मुझे टिप्पणियों में बताएं और मैं इसे अपडेट करूंगा।


मैं फ़ाइलों के नाम में रिक्त स्थान के साथ एक मुद्दा है। मुझे पता चला है कि कोड से पहले `IFS = $ '\ n' 'सेट करना उपयोगी है, (यह एक आंतरिक फ़ील्ड विभाजक को नई लाइन पर सेट करता है) - यदि नाम में नई लाइनें हैं तो फिर से काम नहीं करेगा।
लॉरा कैलिनोइयू

2

आप एक शेल स्क्रिप्ट बना सकते हैं जो grepआपका स्रोत कोड है और आपके प्रोजेक्ट फ़ोल्डर के साथ स्थापित छवियों की तुलना करता है।

यहाँ आदमी (ओं) के लिए GREPऔरLS

आसानी से आप अपने सभी स्रोत फ़ाइल को लूप कर सकते हैं, चित्रों को सरणी या कुछ समान और उपयोग में सहेज सकते हैं

cat file.m | grep [-V] myImage.png

इस ट्रिक से आप अपने प्रोजेक्ट सोर्स कोड में सभी इमेज सर्च कर सकते हैं !!

उम्मीद है की यह मदद करेगा!


2

मैंने एक लुआ स्क्रिप्ट लिखी, मुझे यकीन नहीं है कि मैं इसे साझा कर सकता हूं क्योंकि मैंने इसे काम पर किया था, लेकिन यह अच्छी तरह से काम करता है। मूल रूप से यह ऐसा करता है:

चरण एक- स्थिर छवि संदर्भ (आसान सा, अन्य उत्तरों द्वारा कवर)

  • छवि डायर के माध्यम से पुनरावर्ती रूप से देखता है और छवि नामों को निकालता है
  • .png और @ 2x के चित्र नाम स्ट्रिप्स (आवश्यक नहीं / छवि में उपयोग किया गया है :)
  • स्रोत फ़ाइलों में प्रत्येक छवि नाम के लिए पाठात्मक रूप से खोज करता है (स्ट्रिंग शाब्दिक के अंदर होना चाहिए)

चरण दो- डायनामिक छवि संदर्भ (मजेदार बिट)

  • स्रोत विनिर्देशक युक्त सभी स्ट्रिंग शाब्दिकों की सूची को खींचता है (उदाहरण के लिए,% @)
  • नियमित अभिव्यक्ति के साथ इन तारों में प्रारूप विनिर्देशक को प्रतिस्थापित करता है (उदाहरण के लिए, "फू% dbar" "फू [0-9" * * ") बन जाता है
  • इन regex स्ट्रिंग्स का उपयोग करके छवि नामों के माध्यम से खोजता है

फिर जो कुछ भी खोज में नहीं मिला उसे हटा देता है।

किनारे का मामला यह है कि एक सर्वर से आने वाले छवि नाम को संभाला नहीं जाता है। इसे संभालने के लिए हम इस खोज में सर्वर कोड शामिल करते हैं।


साफ। जिज्ञासा से बाहर वाइल्डकार्ड rexxes के लिए प्रारूप विनिर्देशक बदलने के लिए कुछ उपयोगिता है? बस यह सोचकर कि बहुत सारी जटिलताएँ हैं जिन्हें आपको सभी विनिर्देशक और प्लेटफ़ॉर्म पर सही ढंग से निभाना होगा। (प्रारूप निर्दिष्ट डॉक्स)
एड मैकमैनस

2

आप Xcode के लिए FauxPas ऐप आज़मा सकते हैं । यह लापता छवियों और Xcode परियोजना से संबंधित अन्य मुद्दों / उल्लंघनों के निष्कर्षों में वास्तव में अच्छा है।


ऐसा लगता है कि Xcode 9 के बाद से इसे अपडेट नहीं किया गया है। पुष्टि कर सकता है कि यह Xcode 11. के साथ काम नहीं करता है
Robin Daugherty

2

अन्य उत्तरों का उपयोग करते हुए, यह एक अच्छा उदाहरण है कि दो निर्देशिकाओं पर छवियों को अनदेखा कैसे करें और pbxproj या xcassets फ़ाइलों पर छवियों की घटनाओं को न खोजें (ऐप आइकन और स्प्लैश स्क्रीन के साथ सावधान रहें)। * - theignign-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

2

मैंने इस ढांचे का उपयोग किया: -

http://jeffhodnett.github.io/Unused/

अच्छी तरह से काम करता है! केवल 2 स्थानों पर मैंने देखा कि जब छवि नाम सर्वर से होते हैं और जब छवि संपत्ति का नाम परिसंपत्ति के अंदर छवि के नाम से अलग होता है ...


यह केवल उन छवि फ़ाइलों के लिए नहीं है, जो सीधे संदर्भित हैं। यदि आप जैसे एसेट्स का उपयोग कर रहे हैं, तो यह उपकरण दुर्भाग्य से आपके लिए काम नहीं करेगा।
रॉबिन डौबर्टी

0

अप्रयुक्त चित्रों को खोजने के लिए http://jeffhodnett.github.io/Unused/ का उपयोग करें ।


यह मुझे लगता है कि न तो यह एप्लिकेशन फ़ोल्डर नामों में अच्छी तरह से अंतरिक्ष को संभालता है। और यह मेरे एक बड़े प्रोजेक्ट के लिए काफी धीमा है।
इंगम

0

मैंने अप्रयुक्त छवियों की पहचान करने के लिए एक पायथन स्क्रिप्ट बनाई है: 'unused_assets.py' @ gist । इसका उपयोग इस तरह किया जा सकता है:

python3 unused_assets.py '/Users/DevK/MyProject' '/Users/DevK/MyProject/MyProject/Assets/Assets.xcassets'

स्क्रिप्ट का उपयोग करने के लिए यहां कुछ नियम दिए गए हैं:

  • पहले तर्क के रूप में प्रोजेक्ट फ़ोल्डर पथ को पास करना महत्वपूर्ण है, दूसरे तर्क के रूप में संपत्ति फ़ोल्डर पथ
  • यह माना जाता है कि सभी चित्र Assets.xcassets फ़ोल्डर के भीतर बनाए हुए हैं और इनका उपयोग स्विफ्ट फ़ाइलों के भीतर या स्टोरीबोर्ड के भीतर किया जाता है

पहले संस्करण में सीमाएं:

  • उद्देश्य c फ़ाइलों के लिए काम नहीं करता है

मैं प्रतिक्रिया के आधार पर समय के साथ इसे बेहतर बनाने की कोशिश करूंगा, हालांकि पहला संस्करण अधिकांश के लिए अच्छा होना चाहिए।

कृपया कोड के नीचे खोजें। कोड स्व व्याख्यात्मक होना चाहिए क्योंकि मैंने प्रत्येक महत्वपूर्ण कदम के लिए उपयुक्त टिप्पणियां जोड़ी हैं

# 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!")
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.