By alias, I mean the folder shortcut created when you right-click a folder in Finder and select "Make Alias". I can traverse symbolic links in Terminal with cd
, but it doesn't work on aliases: bash: cd: example-alias: Not a directory
. Is it possible to change directory to an alias's destination in Terminal?
-
I have updated my answer– markhunteCommented Apr 15, 2015 at 8:57
6 Answers
To enable cd'ing into a folder alias I've found the following at Mac OS X Hints.
Compile the source code below with the following command:
gcc -o getTrueName -framework Carbon getTrueName.c
This will create the ‘getTrueName’ executable in the same directory as the source. You can add it to your PATH, or just copy it directly to /usr/bin or /usr/local/bin so it’s easy to access.
C source code for getTrueName (copy the text and save the file as getTrueName.c in your home directory):
// getTrueName.c
//
// DESCRIPTION
// Resolve HFS and HFS+ aliased files (and soft links), and return the
// name of the "Original" or actual file. Directories have a "/"
// appended. The error number returned is 255 on error, 0 if the file
// was an alias, or 1 if the argument given was not an alias
//
// BUILD INSTRUCTIONS
// gcc-3.3 -o getTrueName -framework Carbon getTrueName.c
//
// Note: gcc version 4 reports the following warning
// warning: pointer targets in passing argument 1 of 'FSPathMakeRef'
// differ in signedness
//
// COPYRIGHT AND LICENSE
// Copyright 2005 by Thos Davis. All rights reserved.
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this program; if not, write to the Free
// Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
// MA 02111-1307 USA
#include <Carbon/Carbon.h>
#define MAX_PATH_SIZE 1024
#define CHECK(rc,check_value) if ((check_value) != noErr) exit((rc))
int main ( int argc, char * argv[] )
{
FSRef fsRef;
Boolean targetIsFolder;
Boolean wasAliased;
UInt8 targetPath[MAX_PATH_SIZE+1];
char * marker;
// if there are no arguments, go away
if (argc < 2 ) exit(255);
CHECK( 255,
FSPathMakeRef( argv[1], &fsRef, NULL ));
CHECK( 1,
FSResolveAliasFile( &fsRef, TRUE, &targetIsFolder, &wasAliased));
CHECK( 255,
FSRefMakePath( &fsRef, targetPath, MAX_PATH_SIZE));
marker = targetIsFolder ? "/" : "" ;
printf( "%s%s\n", targetPath, marker );
exit( 1 - wasAliased );
}
Include the following in ~/.bash_profile or create a new file ~/.bash_profile with the following content:
function cd {
if [ ${#1} == 0 ]; then
builtin cd
elif [ -d "${1}" ]; then
builtin cd "${1}"
elif [[ -f "${1}" || -L "${1}" ]]; then
path=$(getTrueName "$1")
builtin cd "$path"
else
builtin cd "${1}"
fi
}
You probably have to restart Terminal to load your modified .bash_profile.
Tested in Yosemite 10.10.2 & gcc 4.2 (Xcode 6.2) and it works.
A similar approach is available at superuser.com
Here is my take on this.
add and load this function to your .profile.
function cd {
thePath=`osascript <<EOD
set toPath to ""
tell application "Finder"
set toPath to (POSIX file "$1") as alias
set theKind to kind of toPath
if theKind is "Alias" then
set toPath to ((original item of toPath) as alias)
end if
end tell
return posix path of (toPath)
EOD`
builtin cd "$thePath";
}
Update.
I used the builtin cd
line shown in @klanomath answer which allows you to override the cd command. So we can now use:
cd /path/to/example-alias
or
cd /path/to/example
The function should return and cd to the original path of the aliases original or the normal path.
I haven't tested the answer by @klanomath, but there used to be a Python library to get the target of an alias, but Carbon support was removed from the Apple frameworks. It can be done in Objective C see https://stackoverflow.com/a/21151368/838253.
The best bet is to use symlinks, but unfortunately Finder does not allow you to create these.
I have written an OS X Service which creates symlinks (which are supported by both Finder and Terminal). This runs the following bash script in a Finder workflow. (Unfortunately it doesn't seem to be possible to post Automator code in a readable format).
for f in "$@"
do
fileSuffix="link"
fileExists=`ls -d "$f $fileSuffix"`
fileNumber=0
until [ $fileExists=="" ]; do
let fileNumber+=1
fileSuffix="link $fileNumber"
fileExists=`ls -d "$f $fileSuffix"`
done
echo "$f $fileSuffix"
ln -s "$f" "$f $fileSuffix"
done
-
1In one sentence you say "The best bet is to use symlinks, but unfortunately Finder does not support this." and then say "... which creates symlinks (which are supported by both Finder and Terminal)" and these appear to contradict each other, so consider rewording it as "Finder does not support this" is ambitious. Also the
curFolder
andlinkFile
variables are unused so why are they there? There should be spaces around the comparison operator e.g.$fileExists == ""
and consider using$(..)
instead of legacy backticks. Commented Apr 14, 2015 at 15:22 -
@user3439894 changed wording. You are correct about the code. I wrote this in 2011, shortly after I got a Mac, and it has worked since, and I have not looked at it since. The unused variables are probably left over from testing. Commented Apr 14, 2015 at 21:37
While a symbolic link (UNIX alias) looks the same as a Finder alias inside Finder, they are two complete different types of aliases.
A symbolic link will only hold the path it leads to and will permanently or temporarily break if the resource is moved or on a disconnected drive or share respectively.
A Finder alias is technically an ordinary file with instructions for the Finder. The Finder can use this information to locate a moved target file/directory to a certain extent. If a target resource of an alias is on a mounted network share point, it also holds information of which Keychain item to use to log you in to the share point in order to open it.
So, unless you write a script or program to read out the Finder alias file, it will not use it as a directory, but as a file in Terminal.
Alternatively, you can remove the current Finder alias and create a symbolic link in its place. Command would be ln -s /path/to/original
to create a symbolic link at the current directory. The path can be a full or relative path.
- @markhunte's applescript worked, but there was a warning message:
osascript[9807:7154723] CFURLGetFSRef was passed an URL which has no scheme (the URL will not work with other CFURL routines)
By the help of this tip, I modified @markunte's applescript to remove above warning message
- @markhunte's applescript is slightly slow because it always invokes the applescript. So following @klanomath's tip which is listed above, I modified the script to invoke the applescript only when target object is alias.
# Overriding cd to enable make alias available in CLI
function cd {
if [ ${#1} == 0 ]; then
builtin cd
elif [ -d "${1}" ]; then
builtin cd "${1}"
elif [[ -f "${1}" || -L "${1}" ]]; then
thePath=`osascript <<EOD
set toPath to ""
tell application "Finder"
set toPath to (POSIX file ((do shell script "pwd")&"/$1")) as alias
set theKind to kind of toPath
if theKind is "Alias" then
set toPath to ((original item of toPath) as alias)
end if
end tell
return posix path of (toPath)
EOD`
builtin cd "$thePath";
else
builtin cd "${1}"
fi
}
Like most any operating system (besides Windows), OS X supports Bash scripts. First create the file on your Desktop (or whatever location you'd like):
touch ~/Desktop/PlexConnect.sh Next, set the permissions of the file such that it is executable:
chmod +x ~/Desktop/PlexConnect.sh You can then edit the contents of the script with your text editor of choice, just make sure it begins with the following line so that the system knows to run it using the shell (Bash):
!/bin/bash
The file can then be double-clicked, launching Terminal and executing it.
A more elegant solution for this, however, may be to create an AppleScript application which runs the command for you. Open the "Script Editor" application and paste in the following:
do shell script "/Applications/PlexConnect-master/PlexConnect.py" with administrator privileges Save this as an "Application," naming it whatever you'd like. When opening it, it will give you OS X's standard password prompt, execute the script, then close itself.
-
How does this answer the question asked on top? While clarifying can you please also fix the formatting of your post?– nohillside ♦Commented Jan 31, 2019 at 9:27
-
What has this to do with aliases as asked in the question Also please format your answer as described in Help Centre apple.stackexchange.com/help/formatting– mmmmmmCommented Jan 31, 2019 at 9:28