How to create a symlink to open a directory in Terminal on Mac osx? - macos

There are certain folders I am cd'ing into all day long...for instance, "dev" which is in my Documents folder.
I had this bright idea to set up symlinks so I could simply type "dev" and Terminal would cd into that directory. This doesn't seem to work though. My two attempts are below.
Anyone know how to do this or is there a better way?
ln -s /Users/kelly/Documents/Dev/ dev
ln -s 'cd /Users/kelly/Documents/Dev/' dev
$ dev
bash: dev: command not found

With a symlink you can use
ln -s your/dev/directory/ dev
but you can only use it in the directory you created it in and in the form of cd dev.
If you just want to type dev at any point, use an alias:
alias dev="cd your/dev/direcrory/"
(this should then be in your ~/.bashrc)

You could use an alias for dev. Add to your ${HOME}/.bashrc
alias dev='cd /Users/kelly/Documents/Dev/'
and bash correctly parses ~ in an alias:
alias dev='cd ~/Documents/Dev/'
Using an alias eliminates the need for the symbolic link at all.

You have to write cd dev in your case, but it might be better for you to use bash aliases...
Write in your $HOME/.bash_aliases file:
alias dev='cd /Users/kelly/Documents/Dev/'
after opening a new terminal executing dev will give you, what you want...

In your $HOME/.bashrc, declare an array which maps directories to aliases.
declare -A __diraliasmap=(
[dev]="/Users/kelly/Documents/Dev"
[other]="/Users/kelly/Documents"
)
Also define a command_not_found_handle function. If defined, this function will be run by bash when a command is not found. In the function, check whether the command which failed is listed as an alias for a directory and, if so, cd to the associated directory.
command_not_found_handle()
{
if [[ ${__diraliasmap[$1]+set} = set ]]; then
builtin cd "${__diraliasmap[$1]}"
else
false
fi
}

Related

how can i make my bash script (.sh) to run locally as a bash command? [duplicate]

If I have a basic Python script, with it's hashbang and what-not in place, so that from the terminal on Linux I can run
/path/to/file/MyScript [args]
without executing through the interpreter or any file extensions, and it will execute the program.
So would I install this script so that I can type simply
MyScript [args]
anywhere in the system and it will run? Can this be implemented for all users on the system, or must it be redone for each one? Do I simply place the script in a specific directory, or are other things necessary?
The best place to put things like this is /usr/local/bin.
This is the normal place to put custom installed binaries, and should be early in your PATH.
Simply copy the script there (probably using sudo), and it should work for any user.
Walkthrough of making a python script available anywhere:
Make a python script:
cd /home/el/bin
touch stuff.py
chmod +x stuff.py
Find out where your python is:
which python
/usr/bin/python
Put this code in there:
#!/usr/bin/python
print "hi"
Run in it the same directory:
python stuff.py
Go up a directory and it's not available:
cd ..
stuff.py
-bash: stuff.py: command not found
Not found! It's as we expect, add the file path of the python file to the $PATH
vi ~/.bashrc
Add the file:
export PATH=$PATH:/home/el/bin
Save it out, re apply the .bashrc, and retry
source ~/.bashrc
Try again:
cd /home/el
stuff.py
Prints:
hi
The trick is that the bash shell knows the language of the file via the shebang.
you can also use setuptools (https://pypi.org/project/setuptools/)
your script will be:
def hi():
print("hi")
(suppose the file name is hello.py)
also add __init__.py file next to your script (with nothing in it).
add setup.py script, with the content:
#!/usr/bin/env python3
import setuptools
install_requires = [
'WHATEVER PACKAGES YOU NEED GOES HERE'
]
setuptools.setup(
name="some_utils",
version="1.1",
packages=setuptools.find_packages(),
install_requires=install_requires,
entry_points={
'console_scripts': [
'cool_script = hello:hi',
],
},
include_package_data=True,
)
you can now run python setup.py develop in this folder
then from anywhere, run cool_script and your script will run.
Just create ~/bin and put export PATH=$PATH:$HOME/bin in your bashrc/profile. Don't mess with the system, it will bite you back, trust me.
Few more things (relevant to the question but not part of the answer):
The other way export PATH=$HOME/bin:$PATH is NOT safe, for bash will will look into your ~/bin folder for executables, and if their name matches with other executables in your original $PATH you will be surprised by unexpected/non working command execution.
Don't forget to chmod+x when you save your script in ~/bin.
Be aware of what you are putting in your ~/bin folder, if you are just testing something or working on unfinished script, its always better to use ./$SCRIPT_NAME from your CWD to execute the script than putting it under ~/bin.
The quick answer is to symlink your script to any directory included in your system $PATH.
The long answer is described below with a walk through example, (this is what I normally do):
a) Create the script e.g. $HOME/Desktop/myscript.py:
#!/usr/bin/python
print("Hello Pythonista!")
b) Change the permission of the script file to make it executable:
$ chmod +x myscript.py
c) Add a customized directory to the $PATH (see why in the notes below) to use it for the user's scripts:
$ export PATH="$PATH:$HOME/bin"
d) Create a symbolic link to the script as follows:
$ ln -s $HOME/Desktop/myscript.py $HOME/bin/hello
Notice that hello (can be anything) is the name of the command that you will use to invoke your script.
Note:
i) The reason to use $HOME/bin instead of the /usr/local/bin is to separate the local scripts from those of other users (if you wish to) and other installed stuff.
ii) To create a symlink you should use the complete correct path, i.e.
$HOME/bin GOOD ~/bin NO GOOD!
Here is a complete example:
$ pwd
~/Desktop
$ cat > myscript.py << EOF
> #!/usr/bin/python
> print("Hello Pythonista!")
> EOF
$ export PATH="$PATH:$HOME/bin"
$ ln -s $HOME/Desktop/myscript.py $HOME/bin/hello
$ chmod +x myscript.py
$ hello
Hello Pythonista!
Just create symbolic link to your script in /usr/local/bin/:
sudo ln -s /path/to/your/script.py /usr/local/bin/script
Putting the script somewhere in the PATH (like /usr/local/bin) is a good solution, but this forces all the users of your system to use/see your script.
Adding an alias in /etc/profile could be a way to do what you want allowing the users of your system to undo this using the unalias command. The line to be added would be:
alias MyScript=/path/to/file/MyScript
i find a simple alias in my ~/.bash_profile or ~/.zshrc is the easiest:
alias myscript="python path/to/my/script.py"
Type echo $PATH in a shell. Those are the directories searched when you type command, so put it in one of those.
Edit: Apparently don't use /usr/bin, use /usr/local/bin
Acording to FHS, the /usr/local/bin/ is the good place for custom scripts.
I prefer to make them 755 root:root, after copying them there.

Behavior of 'cd --' (two hyphens)

I know that cd ~- changes directory to $OLDPWD.
I'm using GNU bash, version 4.4.23(1)-release (x86_64-apple-darwin17.5.0) on a Macbook.
'cd --' appears to have the same behavior as 'cd ~-'.
Why?
With Bash -- is used to specify the end of a command options.
So cd -- means cd.
cd without argument change your current directory to your home directory (like cd ~).
The fact it leads you to your last PWD is a coincidence.
That's not correct. cd -- changes to your home directory, just like cd only. Consider cd -- a pure cd with no options and no parameters given. See also https://unix.stackexchange.com/a/11382.

How to create an alias for .. to mean cd .. in macOS shell

I often find myself typing cd.. (which results in -bash: cd“: command not found) in stead of cd ..
So would like to add an alias for this in my .bashrc or better yet, I would like an alias for .. to mean cd ..
I can't get it to work however; I tried several options:
alias ..=cd .. results in alias ..='cd'
alias ..='cd ..' results in alias ..=''cd'
Also escaping the dots in various ways doesn't work:
alias ..=cd \.\. results in alias ..='cd'
alias ..=cd '\.\.' results in alias ..='cd'
What is correct way to do this right?
This works for me on linux (Ubuntu 16.04) with bash v4.3.46. I believe it won't be any different for macOS.
alias '..'='cd ..'
I assume that you are interested in solutions working for bash.
If you want to solve this with an alias, you have to use a name which starts with a letter, for instance
alias up='cd ..'
Maybe more interesting for you would perhaps a general solution, where typing any directory name would cd to this directory. You can do it by placing into your .bashrc the command
shopt -s autocd
After this, .. would bring you one directory up, ~ would bring you to your home direcory and aunt/bertie would cd you right to your aunt.

Can I add a command to my bash profile whenever I create a new folder?

I've been creating commands that jet me to my folder I want to work within, and it's great, but...
Could there be a way to add the command automatically whenever I create a new folder?
E.g., I make a folder on my comp, and this gets added to my bash profile:
alias foldername='cd /Applications/MAMP/htdocs/foldername/wp-content/themes/foldername'
I'm on a mac; el capitan.
You can create a function in your .bashrc:
# Changes directory to project in htdocs
function project () {
cd "/Applications/MAMP/htdocs/$1"
}
Once you've sourced the bashrc or started a new shell you can navigate through to sub folders of htdocs using
project FOLDER_NAME
If you are willing to install a newer version of bash (via Homebrew, for instance), you can set the autocd option.
$ shopt -s autocd
$ pwd
/Users/me
$ mkdir foo
$ foo
cd foo
$ pwd
/Users/me/foo
The version of zsh that ships with Mac OS X has an identically named option, if you are willing to change shells.
% setopt autocd
% pwd
/Users/me
% mkdir foo
% foo
% pwd
/Users/me/foo
You could also use CDPATH environment variable for this sort of thing (assuming your target directories live under a common directory (or three).
From the POSIX specification for cd:
CDPATH
A <colon>-separated list of pathnames that refer to directories. The cd utility shall use this list in its attempt to change the directory, as described in the DESCRIPTION. An empty string in place of a directory pathname represents the current directory. If CDPATH is not set, it shall be treated as if it were an empty string.
So if you set CDPATH=.:/Applications/MAMP/htdocs/foldername/wp-content/themes you could then just use cd foldername from anywhere to go to /Applications/MAMP/htdocs/foldername/wp-content/themes/foldername... assuming of course that there wasn't a directory foldername in your current directory (if you wanted it to work for that too you would need to invert the order of the items in CDPATH).
Another approach referenced in the comment is the create a simple function that creates and changes to a directory. Aliased to mdcd it does just that creates and on successful creation changes to the directory. I use it in my ~/.bashrc:
mkdircd ()
{
[ -z "$1" ] && {
printf "usage: mdcd <dir>\n";
return 1
}
mkdir -p "$1" && cd "$1" || {
printf "error: unable to create directory '%s'\n" "$1";
return 1
}
return 0
}
...
alias mdcd='mkdircd'
You can give it a try and see if it fits your needs.

alias to source a bash file from another dir and return to current dir

I am trying to source the Firefox addon sdk. To do so, I must cd into the sdk's dir, then run source bin/activate. If I don't cd into that dir, and source directly from whatever path I am in currently, the following happens:
$ source ~/src/devtools/addon-sdk/bin/activate
Welcome to the Add-on SDK. Run 'cfx docs' for assistance.
$ cfx
-bash: cfx: command not found
I want to have an alias for that, which cd's into the sdk, sources it, then returns to my current directory:
alias acfx='cd ~/src/devtools/addon-sdk && source bin/activate && cd "$(dirname "$0")"'
This sources the sdk correctly, but alas does not return to the directory I invoked the alias:
$ acfx
Welcome to the Add-on SDK. Run 'cfx docs' for assistance.
dirname: illegal option -- b
usage: dirname path
I am lost here, how do I return to the original directory? Or specify a 'working directory' for source?
You can execute cd and subsequent command in a sub-shell like this:
(cd ~/src/devtools/addon-sdk && source bin/activate)
If for some reason you don't want to create sub-shell then use cd - to change dir to the the previous dir:
cd ~/src/devtools/addon-sdk && source bin/activate && cd -
You can use the pushd and popd shell builtins:
alias acfx='pushd ~/src/devtools/addon-sdk && source bin/activate && popd'
The $(dirname "$0") trick only works when invoked from a script; on the prompt, $0 will be bash, so you'd try to return to . (because dirname bash prints .). In your case, I'm guessing $0 is something different; maybe -bash?
You can save the previous path and then go to it:
prev_dir=$(pwd); ... your commands ... ; cd $prev_dir
In your case:
alias acfx='prev_dir=$(pwd); cd ~/src/devtools/addon-sdk; source bin/activate; cd $prev_dir'
I am not curious if this solves your original problem. can you try cd to that dir, source , cd to some other temp dir, and then try cfx ? i mean sourcing should not be different whether done from the current dir, or some specific dir. If the script assumes the user to be present in the current dir, then it's wrong. May be in that case adding export PATH=~/src/devtools/addon-sdk:$PATH in script might help

Resources