原文連接ios
更多好文,請關注公衆號 知識小集 (ID: zsxjtip)shell
關於 iOS 13.1 中對 Swift 的使用,可參考 Apple 在 iOS 13.1 中使用 Swift 開發的應用程序macos
樸素的方法是檢查應用程序是否在其 Frameworks 文件夾中包含 Swift 庫:libswiftCore.dylib
、libswiftFoundation.dylib
等。swift
如下是 macOS 10.12.1 中的 MRT.app 的 Frameworks 文件夾的內容 /System/Library/CoreServices/MRT.app/Contents/Frameworks/
:bash
可是,這不是一個好方法,由於 iOS 和 macOS 在 /System/Library/PrivateFrameworks/Swift/
中包含 Swift 庫的私有副本。iOS 和 macOS 中的多個應用程序直接連接到這些系統庫。app
如下是 macOS 10.12.1 中的 PIPAgent.app
的 Frameworks 文件夾的內容 /System/Library/CoreServices/PIPAgent.app/Contents/Frameworks/
:函數
更好的方法是檢查二進制文件是否連接到 Swift 庫。能夠經過命令行工具 otool 中使用 -L
選項輕鬆完成此操做:工具
-L
顯示目標文件使用的共享庫的名稱和版本號,以及若是文件是共享庫,則顯示共享庫 ID。oop
在 PIPAgent 應用程序上運行此命令時:ui
otool -L /System/Library/CoreServices/PIPAgent.app/Contents/MacOS/PIPAgent | grep swift
複製代碼
您將得到如下輸出:
/System/Library/PrivateFrameworks/Swift/libswiftAppKit.dylib (compatibility version 1.0.0, current version 800.8.18)
/System/Library/PrivateFrameworks/Swift/libswiftCore.dylib (compatibility version 1.0.0, current version 800.8.18)
/System/Library/PrivateFrameworks/Swift/libswiftCoreData.dylib (compatibility version 1.0.0, current version 800.8.18)
/System/Library/PrivateFrameworks/Swift/libswiftCoreGraphics.dylib (compatibility version 1.0.0, current version 800.8.18)
/System/Library/PrivateFrameworks/Swift/libswiftCoreImage.dylib (compatibility version 1.0.0, current version 800.8.18)
/System/Library/PrivateFrameworks/Swift/libswiftDarwin.dylib (compatibility version 1.0.0, current version 800.8.18)
/System/Library/PrivateFrameworks/Swift/libswiftDispatch.dylib (compatibility version 1.0.0, current version 800.8.18)
/System/Library/PrivateFrameworks/Swift/libswiftFoundation.dylib (compatibility version 1.0.0, current version 800.8.18)
/System/Library/PrivateFrameworks/Swift/libswiftIOKit.dylib (compatibility version 1.0.0, current version 800.8.18)
/System/Library/PrivateFrameworks/Swift/libswiftObjectiveC.dylib (compatibility version 1.0.0, current version 800.8.18)
複製代碼
使用 otool 命令行工具,能夠很容易地編寫一個 bash 函數來判斷文件是不是連接到 Swift 庫的二進制文件:
#------------------------------------------------------------------------
# Function to check if a file (passed as argument $1) is using Swift
# It returns the number of occurrences of the string 'swift'
# from the output of otool
#------------------------------------------------------------------------
isFileUsingSwift ()
{
otool -L $1 2>/dev/null | grep -o swift | wc -l
}
複製代碼
若是文件是連接到 Swift 庫的二進制文件,則 processFile
bash 函數將文件做爲參數並打印其路徑:
#------------------------------------------------------------------------
# Function to process a file (passed as argument $1).
# It calls the function isFileUsingSwift() to determine
# if this is a binary using Swift and in this case
# print the path of this file.
#------------------------------------------------------------------------
processFile ()
{
isFileUsingSwift=$( isFileUsingSwift $1 )
if [ ${isFileUsingSwift} != 0 ]
then
# We found a binary using Swift
echo " $1"
fi
}
複製代碼
如今遍歷文件夾的全部文件僅需一行:
find ${PATH_TO_CHECK} -type f -exec bash -c 'processFile "$0"' {} \;
複製代碼
下面是一個完整的 bash 腳本,該腳本循環遍歷一個文件夾的全部文件,並顯示找到的全部使用 Swift 的二進制文件的路徑。
#!/bin/bash
#---------------------------------------------------------------------
# Bash script that loops through all the files of a folder and
# print the paths of all the binaries found that use Swift
# Created by Alexandre Colucci on 01.11.2016
# https://blog.timac.org/2016/1101-apples-use-of-swift-in-ios-10-1-and-macos-10-12
#---------------------------------------------------------------------
#---------------------------------------------------------------------
# Force expand a wildcard pattern into the list of matching pathnames
#---------------------------------------------------------------------
shopt -s nullglob
#---------------------------------------------------------------------
# Function to print the usage
#---------------------------------------------------------------------
printUsage ()
{
echo "Usage: detectSwift.sh PATH"
echo "PATH: Folder to search for binaries using Swift"
echo ""
echo "Examples:"
echo " detectSwift.sh /System/Library"
echo " detectSwift.sh /System"
echo " detectSwift.sh /"
echo ""
echo "Note: run as root in order to avoid permission issues."
echo ""
}
#---------------------------------------------------------------------
# Function to check if a file (passed as argument $1) is using Swift
# It returns the number of occurrences of the string 'swift'
# from the output of otool
#---------------------------------------------------------------------
isFileUsingSwift ()
{
otool -L $1 2>/dev/null | grep -o swift | wc -l
}
#---------------------------------------------------------------------
# Function to process a file (passed as argument $1).
# It calls the function isFileUsingSwift() to determine
# if this is a binary using Swift and in this case
# print the path of this file.
#---------------------------------------------------------------------
processFile ()
{
isFileUsingSwift=$( isFileUsingSwift $1 )
if [ ${isFileUsingSwift} != 0 ]
then
# We found a binary using Swift
echo " $1"
fi
}
#---------------------------------------------------------------------
# Check if the script was called with the expected usage
#---------------------------------------------------------------------
PARAMETER_NUMBER=$#
PARAMETER_REQUIRED=1
if [ $PARAMETER_NUMBER != $PARAMETER_REQUIRED ];
then
printUsage
exit 1
fi
#---------------------------------------------------------------------
# Get the folder path
#---------------------------------------------------------------------
PATH_TO_CHECK=$1
echo ""
echo "Start time:"
date
echo ""
echo "Apps using Swift in ${PATH_TO_CHECK}"
#---------------------------------------------------------------------
# Export the functions so that the subshell inherits them
#---------------------------------------------------------------------
export -f isFileUsingSwift
export -f processFile
#---------------------------------------------------------------------
# Find all the regular files in all subdirectories
# and call for each the function processFile()
#---------------------------------------------------------------------
find ${PATH_TO_CHECK} -type f -exec bash -c 'processFile "$0"' {} \;
#---------------------------------------------------------------------
# Finalizing
#---------------------------------------------------------------------
echo ""
echo "Completed at:"
date
echo ""
複製代碼
該腳本確實很慢:對於每一個常規文件,它將建立一個 subshell,分別調用otool
,grep
和 wc
。
在 iOS 10.1 文件系統上運行此腳本大約須要 30 分鐘。
對於 macOS 10.12.1,在 /
路徑上運行腳本須要花費數十個小時。 我建議僅在 /System
,/Applications
和 /usr
上運行此腳本。並行處理這 3 個文件夾大約須要 2 個小時。