Hi @JMichaelTX,
Thank you very much.
Sure. So the scripting portion I did already, which looks like this:
cd "$(osascript \
-e 'tell application "Finder" to ¬' \
-e 'get the POSIX path of ¬' \
-e '(the insertion location as text)')"
Breaking it down (for the benefit of anyone else wishing to learn what's happened here), there are two separate commands used here:
osascript
: This is the shell program that executes AppleScripts (or JavaScripts) either by way of a script file that is provided as the argument (which isn't done here, because I'm not using a script file), or by way of plain text specified line-by-line by each use of the -e
option. You can use the -e
option as many times as you like, with each occurrence being one line of AppleScript code that combine to form a complete script. Alternatively, you can use a single -e
option, the write the text out fully between a pair of opening and closing quotes that includes linefeeds, etc:
osascript -e "tell application \"Finder\" to ¬
get the POSIX path of ¬
(the insertion location as text)"
The result of the script is written to stdout
, which in my case was /Users/CK/Downloads/Safari Downloads/
cd
: The built-in bash command that lets one set the present working directory to the path specified by the argument supplied, e.g. cd ~/Downloads
to be now working in the Downloads
directory of my home folder.
In addition to these two commands, there's a special bash pseudo-"function" of sorts (really more of an expression or operator) that allows one to perform a command substitution, which is where a shell command can have its output be substituted in place of an argument to be used by another command:
$(...)
: This syntax is a dollar ($
) symbol following by a pair of opening and closing parentheses, between which one can write a regular shell command, which the ellipsis represents here. The shell then runs the command inside the parentheses, and whatever result it returned by the command gets pasted in place of the syntax. For example, cd $(echo ~/Downloads)
has the same ultimate outcome as cd ~/Downloads
, but uses echo
that would typically print the text "~/Downloads" to stdout
, which in this situation means it gets returned to be substituted in place of the $()
and become the argument supplied to cd
.
My use of it in the snippet takes the form cd $(osascript ...)
. As in the previous example, osascript
inside the paranetheses gets run as it would normally by the shell, and the output of that script when executed independently was, I stated before, /Users/CK/Downloads/Safari Downloads/
. This then serves as a replacement to $()
and the substituted path then becomes the argument upon which cd
acts, taking me to the Safari Downloads
folder, just in the same way as it would had I written the command explicitly as cd "/Users/CK/Downloads/Safari Downloads/"
.
Although, note here I've used double quotes to encapsulate the string so it is read as a single argument, otherwise the space in the word Safari Downloads
would serve to separate it into two separate arguments, and the command would fail because I don't have a folder called Safari
in my Downloads
folder, nor one called Downloads
in the directory I was presently working in.
I also, therefore, was sure that I included the quotes even when using the command substitution syntax, and the actual form of the command is cd "$(osascript ...)"
.
Aliases and Functions
Functions
Now, for what I left out in my original reply, and the part that addresses you question, which relates to my suggestion that an alias or function be defined that can store the command and be executed whenever the name of the alias or function is entered into the command line.
To define ppath
as a function in bash, you would declare it like this:
function ppath {
cd "$(osascript \
-e 'tell application "Finder" to ¬' \
-e 'get the POSIX path of ¬' \
-e '(the insertion location as text)')"
}
Then, for as long as the instance of the current shell is running, you can type ppath
and use it just like any other command line tool, the effect of which is to cd
me into the directory output from the osascript
.
However, when the shell session ends, the function no longer exists, and won't be available when one next opens Terminal.
The two methods of which I'm aware to store a function and have it remain available to use at any time in the future and across all shell instances is:
① To have the function become part of a bash script that is saved as a file, then put in one of the directories specified by the $PATH
environment variable, which tells you where the shell searches to find the executable script files whenever a command is called upon. The file would look like this:
#!/bin/bash
cd "$(osascript \
-e 'tell application "Finder" to ¬' \
-e 'get the POSIX path of ¬' \
-e '(the insertion location as text)')"
and would be saved simply as ppath
(no file extension is needed). Then it is made executable by running the command: chmod +x /path/to/ppath
. Finally, it is moved into a directory that allows bash to find it without having to type out the full path to the file. In my case, I moved it to /usr/local/bin
to run a test.
② The other way, is to store the function declaration inside ~/.bashrc
, which is used to initialise each instance of the shell when it's first created. Therefore, it'll ensure the function is freshly defined and available to be called whenever a new shell is opened. If the ~/.bashrc
file doesn't exist, you can create it.
The difference in how these two options have ppath
declared is in the use or omission of the function
command: if saving it as a file, you can see I omitted it. It's not needed in such a simple script, so remains in the main body of the file. The filename becomes the label used to call on the command to execute. Conversely, if you're adding the definition of ppath
to ~/.bashrc
, you need to use the function
command to provide a wrapper to contain the commands and separate them from other functions you might have defined in that file. So that's where you define function ppath { ... }
, where it's the function name that provides the label with which to call upon and execute the commands contained within.
Aliases
As the name implies, an alias
in bash is essentially a shortcut for commonly used terms, enabling one to define a synonym that refers to another command in the shell. Often it's used to help reduce the amount one has to type by using aliases that have short names refer to a longer command expression.
The declaration is in the form of alias ⟨name⟩="⟨command⟩"
, where alias
is the literal command used to create an alias for a given command ⟨command⟩
and have it assigned to the label ⟨name⟩
with which one wishes to use to invoke the command's execution.
For example, find
has an annoyingly long and wordy syntax to achieve anything useful, and I often might be typing out the same lengthy command to find files in a particular folder in Finder that are over 4 weeks old, with either a .jpg
or .mov
file extension, and either having been exported as a movie or it having extended attributes (which includes Finder tags)
find "/Users/CK/Pictures/Photo Booth Library/Pictures" -depth 1 -type f -Btime +4w \
\( -name '*.jpg' -or -name '*.mov' \) \( -name '*.export.mov' -or -xattr \)
Rather than declaring a function, which is a bit overkill given the complex things one can do with a function, but not need to do in this instance, an alias
is a lot more limited in what it can be used for, but also very simple and made-for-purpose.
alias oldPhotos="find '/Users/CK/Pictures/Photo Booth Library/Pictures' \
-depth 1 -type f -Btime +4w \
\( -name '*.jpg' -or -name '*.mov' \) \
\( -name '*.export.mov' -or -xattr \)"
Now the same command can be called by typing oldPhotos
.
Here's a nice page I came across demonstrating some practical uses for alias
, which isn't always just about reducing one's typing efforts.
Now to implement it with the original bash command relating to this thread, one would definte ppath
as an alias like this:
alias ppath='cd "$(osascript <<<"tell application \"Finder\" to get the POSIX path of (the insertion location as text)")"'
I've altered the way I supplied the arguments to osascript
here, utilising a here string, denoted by <<<
, which passes the string to the right into the standard input of the command on the left as an argument. There's another similar notation of the form <<
, called a heredoc, which is for delivering multi-line input, essentially enabling one to author an entire file on the command line and have it delivered as an argument, as one would do by supplying a path to a file, but instead chooses to supply its contents.
alias ppath='cd "$(osascript <<OSA
tell application "Finder" to return ¬
the POSIX path of ¬
(the insertion location as text)
OSA
)"'
The main reason for changing it for the alias declaration was because there were a lot of quotes being used in its original form, and it was tough trying to get them to open and close happily, and a here string and heredoc each eliminate a layer of quotation marks (though there are more important reasons one might employ them in other places, mostly in considering how and when new shell processes get spawned depending on the way a chain of commands is formed).
As before when declaring the function on the command line, the lifespan of the alias will be however long that shell remains running. In order to get ut initialised each time a new shell is created, add the declaration to the ~/.bashrc
file.
I hope that helps you and anybody else in some way. I apologise it's such a lengthy reply, but I didn't know how much detail was appropriate, so approached from an assumption that a reader may have almost zero Bash experience, which I know isn't the case for you or the OP.