Swift调用Bash执行mobiledevice完整命令提示“command not found”求助
mobiledevice in Swift's Process Hey there! I see you're running into a "command not found" error when trying to execute the full mobiledevice get_device_prop DeviceName command from your Swift function, even though running just mobiledevice works. Let's break down what's happening and fix it.
The Root Cause
When you launch bash with --login, it loads a specific set of profile files (like .bash_profile, .bashrc) that might not include the directory where mobiledevice is installed. Your terminal session probably has the correct PATH environment variable to find mobiledevice, but the Process instance in Swift doesn't inherit that same full environment by default—especially when using --login which can reset or modify the path.
Fix 1: Use the Absolute Path to mobiledevice
The simplest fix is to call mobiledevice using its full absolute path. First, find where it's installed by running this in your terminal:
which mobiledevice
This will return something like /usr/local/bin/mobiledevice. Then update your Swift function to use that path:
func getConnectedDevices(lblOut: NSTextView) { let pipe = Pipe() let process = Process() // Replace with the path from `which mobiledevice` let mobiledeviceAbsolutePath = "/usr/local/bin/mobiledevice" process.launchPath = "/bin/bash" process.arguments = ["--login", "-c", "\(mobiledeviceAbsolutePath) get_device_prop DeviceName"] process.standardOutput = pipe let fileHandle = pipe.fileHandleForReading process.launch() // Avoid force-unwrapping to prevent crashes if output is invalid if let output = String(data: fileHandle.readDataToEndOfFile(), encoding: .utf8) { lblOut.string += "\n" + output } else { lblOut.string += "\nError: Could not read command output" } }
Fix 2: Explicitly Set the PATH Environment Variable
If you prefer not to hardcode the path, you can add the directory containing mobiledevice to the Process environment's PATH:
func getConnectedDevices(lblOut: NSTextView) { let pipe = Pipe() let process = Process() // Get the current environment and add the mobiledevice directory to PATH var environment = ProcessInfo.processInfo.environment let mobiledeviceDirectory = "/usr/local/bin" // Replace with the correct directory if let existingPath = environment["PATH"] { environment["PATH"] = "\(mobiledeviceDirectory):\(existingPath)" } else { environment["PATH"] = mobiledeviceDirectory } process.environment = environment process.launchPath = "/bin/bash" process.arguments = ["--login", "-c", "mobiledevice get_device_prop DeviceName"] process.standardOutput = pipe let fileHandle = pipe.fileHandleForReading // Use run() instead of launch() (Swift 5.3+ recommended) do { try process.run() process.waitUntilExit() if let output = String(data: fileHandle.readDataToEndOfFile(), encoding: .utf8) { lblOut.string += "\n" + output } else { lblOut.string += "\nError: Could not read command output" } } catch { lblOut.string += "\nError running command: \(error.localizedDescription)" } }
Bonus: Use run() Instead of launch()
Note that launch() is deprecated in newer Swift versions. Using try process.run() with proper error handling is more robust, as shown in Fix 2.
内容的提问来源于stack exchange,提问作者Bilal

