Get path to Swift script from within script
just in swift:
let cwd = FileManager.default.currentDirectoryPath
print("script run from:\n" + cwd)
let script = CommandLine.arguments[0];
print("\n\nfilepath given to script:\n" + script)
//get script working dir
if script.hasPrefix("/") { //absolute
let path = (script as NSString).deletingLastPathComponent
print("\n\nscript at:\n" + path)
} else {
let urlCwd = URL(fileURLWithPath: cwd)
if let path = URL(string: script, relativeTo: urlCwd)?.path {
let path = (path as NSString).deletingLastPathComponent
print("\n\nscript at:\n" + path)
}
}
Run swift script inside bash script
You can call swift -
to read the source from standard input,
and a "here document"
to provide the inline Swift code.
Example: Contents of x.sh
:
echo "Before running Swift"
xcrun swift - /path/path2/path3/path4 <<'EOF'
import Foundation
let path = CommandLine.arguments[1]
print(path)
EOF
echo "After running Swift"
Running the script:
$ bash x.sh
Before running Swift
/path/path2/path3/path4
After running Swift
Or, if you want to read the Swift code from a variable:
APP="
import Foundation
let path = CommandLine.arguments[1]
print(path)
"
echo "Before running Swift"
xcrun swift - /path/path2/path3/path4 <<< "$APP"
echo "After running Swift"
Execution Path for Swift Script
When you run yourScript
, in Terminal.app, do you more or less $> ./yourScript
, right?
When, do you for instance a cd
, you can do cd ./thePathYouWant
, right? ./thePathYouWant
is a parameter (also named launch arguments or options)
In your Swift script, you can read that retrieve all the parameters with CommandLine.arguments
.
Now, I guess that you script needs to know some folder or some file before acting.
So, in a simplified way, of launching your script like that:
./yourScript ./Folder/File
You can read ./Folder/File
with CommandLine
.
Now, you can check if you find File
at that path.
The whole logic could be in pseudo code:
// Parameter Path was provided, and is "correct"
if let parameterPath = parameterPath, checkExistenceOfFile(at: parameterPath) {
//Work normally
// Parameter path was not provided or incorrect, we check if the file exists at this level
} else if checkExistenceOfFile(at: "./File") { //"./File" being the default path, we expect it to be launch at the same level
//Work normally
// We couldn't find the path
} else {
print("File not not found, you can execute the script like this: $>\n./yourScript ./Folder/File where "./Folder/File" is the path of the file, or execute $>./yourScript where the file is on the same folder
}
Reliable way for a Bash script to get the full path to itself
Here's what I've come up with (edit: plus some tweaks provided by sfstewman, levigroker, Kyle Strand, and Rob Kennedy), that seems to mostly fit my "better" criteria:
SCRIPTPATH="$( cd -- "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
That SCRIPTPATH
line seems particularly roundabout, but we need it rather than SCRIPTPATH=`pwd`
in order to properly handle spaces and symlinks.
The inclusion of output redirection (>/dev/null 2>&1
) handles the rare(?) case where cd
might produce output that would interfere with the surrounding $( ... )
capture. (Such as cd
being overridden to also ls
a directory after switching to it.)
Note also that esoteric situations, such as executing a script that isn't coming from a file in an accessible file system at all (which is perfectly possible), is not catered to there (or in any of the other answers I've seen).
The --
after cd
and before "$0"
are in case the directory starts with a -
.
Is there a way to have a Swift script use multiple files
There's a better way!
#!/usr/bin/swift -frontend -interpret -enable-source-import -I.
import other_file // this imports other_file.swift in the same folder
funcFromOtherFile()
if you want to import files from ExampleFolder
it would be like:
#!/usr/bin/swift -frontend -interpret -enable-source-import -I./ExampleFolder
import other_file // this imports ./ExampleFolder/other_file.swift
funcFromOtherFile()
How to get the current directory in iCloud Drive of macOS with Swift script?
You need to encode the string since it contains a space
path = "/Users/myname/Library/Mobile Documents/com~apple~CloudDocs/MyScripts"
if let encoded = path.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed),
let url = URL(string: encoded) {
print(url)
}
/Users/myname/Library/Mobile%20Documents/com~apple~CloudDocs/MyScripts"
How do I run a terminal command in a Swift script? (e.g. xcodebuild)
If you don't use command outputs in Swift code, following would be sufficient:
#!/usr/bin/env swift
import Foundation
@discardableResult
func shell(_ args: String...) -> Int32 {
let task = Process()
task.launchPath = "/usr/bin/env"
task.arguments = args
task.launch()
task.waitUntilExit()
return task.terminationStatus
}
shell("ls")
shell("xcodebuild", "-workspace", "myApp.xcworkspace")
Updated: for Swift3/Xcode8
Related Topics
Select Next Nstextfield with Tab Key in Swift
Uicollectionviewcell Register Class Fails, But Register Nib Works
Initialization of 'Unsafemutablerawpointer' Results in a Dangling Pointer
Xcode 6 Beta/Swift - Playground Not Updating
iOS 13.1 Uitextview Delegate Method Shouldinteract Called When Scrolling on Attachment
Optional Chaining with Swift Strings
Swift Combine - Wait for All Publishers
Swift: Assigning Function to Variable
How to Capture Local Variable Inside an Async Closure in Swift
How to Cancel Dispatchqueue.Main.Asyncafter(Deadline: Time) in Swift3
React Native Sending Events to JavaScript in Swift
Xcode 9 - Test Target X Encountered an Error (Unable to Connect to Test Manager)
How to Remove All Nodes from a Scenekit Scene
Rxswift: Observable While a Button Holds Down
Scrollbar Incorrectly Appears Underneath Uicollectionview Section Header
Add Links to Swift Classes in the Quick Help Documentation Comments