Park Directories allows a user to navigate to any directory on their system with the simplicity of the semantics of the cd command. Do you have a few directories in which you work commonly: the root to your dev directory, /var/log, the root directory of your current project? When you open your terminal, how do you jump to one of these? Do you have aliases for them? Do you have to type them out with tab completion a lot? Does it get tedious? When you want to jump to another part of your system and stay there for a while, are you tempted to open a new terminal window or another tab, or another tmux pane so that you can come back to where you are without having to navigate back tediously?
There are a few popular implementations that allow us to go back to the last directory easily using the command cd -
. This is really handy, but what happens when you need to navigate around the tree for a bit before going back to where you were?
With Park Directories, this is easy. Park (i.e. bookmark or alias) the current directory by typing pd -a NAME
. Go wherever you'd like on your system. When you're ready to return to where you were, type pd NAME
, and you're back!
No need to park every frequently used directory. Park a home base and navigate to directories relative to the target of the reference name: pd proj/src
.
You can use Bash's popular autocomplete feature to quickly access your parked directory aliases, directory paths relative to a target directory, short and long options, and more with the press of a <tab>
or two.
Park Directories was designed with scriptability in mind. You can perform multiple actions on the same line, and you can park any directory by providing the full path to the directory: pd -a NAME FULL_PATH
. This could be useful when you are getting ready to work on a project and want to park your project root, the debug build directory, the release build directory, the log directory, and maybe the deploy directory. You could use the same generic names to reference all of these and use a script to set up your environment. Something like the following:
#!/bin/bash
# Remove references, if they exist
pd -d proj -d dbg -d rel -d log -d dep
# Add references
# These could all be executed in the same invocation, but it's easier to read and understand
# on multiple lines.
pd -a proj /home/user/docs/dev/super-awesome-project # project directory
pd -a dbg /home/user/docs/dev/super-awesome-project/bin/debug # debug build directory
pd -a rel /home/user/docs/dev/super-awesome-project/bin/release # debug build directory
pd -a log /home/user/log # log directory
pd -a dep /var/www/html/super-awesome-project # deploy directory
NOTE Reference names may not contain a forward slash '/'.
$ pd -a proj/build ERROR: Reference name may not contain '/'
The references persist across Bash sessions.
Easily remove a bookmark with pd -d NAME
. Show the list of all parked directories with pd -l
, and when you want to totally clean house, just type pd -c
and all of the references will be removed.
Park Directories is currently being developed as a Bash utility. Keep an eye on the project's roadmap for more about what's coming next.
It's easy to get started!
Download or clone the repository, and then install it.
git clone https://github.com/nb-twy/ParkDirectories.git
cd ParkDirectories
./install.sh
source ~/.bashrc
Without any switches, install.sh will add the pd command to the environment, place the Bash executable in your $HOME
directory, and place the bootstrap code in the .bashrc file. Installation is fast! Follow the instructions at the end of the installation and run source ~/.bashrc
or restart your terminal to bootstrap the command.
The first time you run pd with any of its options (e.g. pd -h
to see the help information), the data file (.pd-data by default) will be created in the same directory as the executable. The command is not complicated, so just run pd -h
to see all of the options in a quick view.
# Navigate to a directory you'd like to park
> cd ~/home/dev
# Park your first directory
> pd -a dev
# Navigate around a bit
> cd /var/log
> cd /etc
> cd ~/.ssh
# Easily return to your dev directory
> pd dev
# Add a couple of your favorite directories with one command
> pd -a www /var/www/html/mysite -a pic ~/home/documents/pictures
# Quickly navigate to the root of your web site
> pd www
Read below to learn more about the features and functionality of Park Directories.
Have fun zooming around your system!
Most of what you need to know to be successful with Park Directories is right in the help text.
$ pd -h
Park Directories
Park (bookmark) directories so that we can quickly navigate
to them from anywhere else using a short reference name.
The references persist across bash sessions.
usage: pd [REF[/RELPATH]] [OPTION {ARG} [OPTION {ARG} ...]]
-h, --help Display this help message
-a, --add NAME[ PATH] Given just NAME, park the current directory with reference NAME
Given NAME & PATH, park PATH with reference NAME
Reference names may not start with - or contain /
-d, --del NAME Remove the directory referenced by NAME
-l, --list Display the entire list of parked directories
-c, --clear Clear the entire list of parked directories
-x, --expand NAME[/RELPATH] Expand the referenced directory and relative path without
navigating to it
-e, --export FILE_PATH Export current list of parked directories to FILE_PATH
-i, --import Import list of parked directories from FILE_PATH
[--append | --quiet] FILE_PATH Use -i --append FILE_PATH to add entries to the existing list
Use -i --quiet FILE_PATH to overwrite current entries quietly
-v, --version Display version
Examples:
pd dev Navigate to directory saved with the ref name dev
pd dev/proj Navigate to the proj subdirectory of the directory
referenced by ref name dev
pd -a dev Park the current directory with the ref name dev
pd -a log /var/log Park /var/log with ref name log
pd -d dev Remove the directory referenced by the name dev from
the parked directories list
Move the contents of the directory referenced by dev1 to the archive
subdirectory of the directory referenced by repos:
mv -v \$(pd -x dev1) \$(pd -x repos/archive/)
A single invocation can take multiple options, performing multiple operations at once:
pd -l -d dev -a dev -d log -a log /var/log -l
This command will
1) List all parked directories
2) Remove the entry referenced by "dev", if one exists
3) Park the current directory with the reference name "dev"
4) Remove the entry referenced by "log", if one exists
5) Park the /var/log directory with the reference name "log"
6) List all parked directories
Parked directories are stored in /home/user/.pd-data
Park Directories version 2.0.0
Let's park the root of your dev directory with the name dev. First navigate to this directory. Then execute
$ cd /home/user/nix0/mydocs/dev
$ pd -a dev
Added: dev --> /home/user/nix0/mydocs/dev
You're working on a particular dev project, so you go there and park that directory.
$ cd my_project
$ pd -a proj
Added: proj --> /home/user/nix0/mydocs/dev/my_project
Your app logs are stored in /var/log/my_project. We don't have to go there. Let's just park it from here.
$ pd -a log /var/log/my_project
Added: log --> /var/log/my_project
You're developing a website, so your output will go to /var/www/html/my_project, so let's park that, too, without traveling there.
$ pd -a html /var/www/html/my_project
Added: html --> /var/www/html/my_project
Let's head back and work on my_project for a while. What did we name the bookmark for my_project code?
$ pd -l
dev /home/jsmith/documents/dev
proj /home/jsmith/documents/dev/my_project
log /var/log/my_project
html /var/www/html/my_project
Right, proj!
$ pd proj
Something is going wrong, so you want to check out the logs for a bit.
$ pd log
It looks like there might be a deployment issue, so you want to take a look at what was deployed to /var/www/html/my_project. Did you park that directory as html or http? Let's use autocomplete.
$ pd h<tab>
$ pd html # That's right! It was html.
You identify the problem and want to get back to your code.
$ pd proj
In a couple of weeks, you're done working on this project and don't need the bookmarks anymore.
# Note that the following command removes (-d) the references to proj, html, and log
# and then lists (-l) the remaining references. This is a good pattern when you're
# deleting more than one reference.
$ pd -d proj -d html -d log -l
Removed: proj --> /home/jsmith/documents/dev/my_project
Removed: html --> /var/www/html/my_project
Removed: log --> /var/log/my_project
dev /home/jsmith/documents/dev
If you don't need any of the bookmarks anymore, you can clear the entire list quickly.
$ pd -c
Removed all parked directories
A big time saver is the ability to navigate to a directory relative to the parked directory. For example, you are working on a software application called MyApp with top-level directories docs, src, and tests.
# Park the app root directory
> pd -a app
Added: app --> /home/user/dev/apps/MyApp
# At some point, you're deep in the docs folder structure
> pwd
/home/user/dev/apps/MyApp/docs/getting_started/install
# You want to go look at the files in the src directory
> pd app/src
> pwd
/home/user/dev/apps/MyApp/src
Use tab completion to quickly find the ref name you're looking for. This works with navigation (pd REF
), deletion (pd -d REF
), and expansion (pd -x REF
).
> pd d<tab><tab>
dev dlp docs
> pd do<tab>
> pd docs/
> pwd
/home/user/documents
Use tab completion to quickly navigate to directories relative to the target directory of the parked reference.
> pd d<tab><tab>
dev dlp docs
> pd de<tab>
> pd dev/<tab><tab>
experiments foo projA projB projC projD
> pd dev/p<tab>
> pd dev/proj<tab><tab>
projA projB projC projD
> pd dev/projB/
> pwd
/home/user/dev/my_ui_project_B
If you are using the import feature (pd -i MAPPING_FILE
) or parking a directory with the path (pd -a REF PATH
), you can use autocomplete to easily find the file or directory.
# Look for a file to import
> pd -i <tab><tab>
httpd.conf.bck ssh.conf.bck park-directories.bck
> pd -i p<tab>
> pd -i park-directories.bck
# Look for a directory to park
> pd -a logs /var/log/<tab><tab>
apt my_app1_logs my_app2_logs ssh_logs
> pd -a logs /var/log/my<tab>
> pd -a logs /var/log/my_app<tab><tab>
my_app1_logs my_app2_logs
> pd -a logs /var/log/my_app2<tab>
> pd -a logs /var/log/my_app2_logs/
Added: logs --> /var/log/my_app2_logs
If you can't remember one of the actions/options, just type -
or --
and then let autocomplete do the rest. If you can't remember what each option does, don't forget pd -h
or pd --help
.
> pd -<tab><tab>
-a -c -d -e -h -i -l -v -x
> pd --<tab><tab>
--add --clear --del --expand --export --help --import --list --version
If you want to backup your list of parked directories or want to automate configuring another system, you can easily export your list of parked directories to a file using the -e|--export
option.
$ pd -e my-parked-directories.txt
List of parked directories exported to my-parked-directories.txt
If you have exported a list of parked directories, created your own by hand, or received a file from a friend, you can import your list. You can either overwrite the current list or append the new entries to the current list.
Append to List
You append to the list by using the -i --append FILE_PATH
option. You can append entries and check that they were added all in one go by adding the -l
option to the end of the command.
$ pd -i --append my-parked.directories.txt -l
Import complete
dev /home/user/docs/dev
pd /home/user/docs/dev/ParkDirectories
Interactive Overwrite
When you import entries without a second option, the current contents will be overwritten, but you will have the chance to decide what to do first. You can
- backup the current contents
- overwrite without a backup
- abort the import
$ pd -i my-parked-directories.txt
WARNING: Import will replace the current list of parked directories!
Please choose from the following options:
(b)ackup current list and continue
(c)ontinue without backing up
(a)bort import
[b/c/a]: a
Import aborted!
$ pd -i my-parked-directories.txt
WARNING: Import will replace the current list of parked directories!
Please choose from the following options:
(b)ackup current list and continue
(c)ontinue without backing up
(a)bort import
[b/c/a]: b
Data file backed up to /home/user/.pd-data-1591339470.bck
Contents of data file cleared
Import complete
$ pd -i my-parked-directories.txt
WARNING: Import will replace the current list of parked directories!
Please choose from the following options:
(b)ackup current list and continue
(c)ontinue without backing up
(a)bort import
[b/c/a]: c
Contents of data file cleared
Import complete
Useful for scripted configurations is the ability to overwrite without any user interaction.
$ pd -i --quiet my-parked-directories.txt
Contents of data file cleared
Import complete
The install script, install.sh, has several options that allow you to customize your installation. Let's walk through each of these options.
>>>> Install Park Directories <<<<
usage: install.sh [OPTIONS]
OPTIONS:
-h, --help Display this help message and exit
-d, --dir DIR Set the directory where the data file and executable
will be written. Use a fully-qualified path or /home/user
will be used as the root path. (default: /home/user)
-p, --profile PROFILE Install the bootstrap code in the specified profile file
Requires full path (e.g. ~/.bash_profile, ~/.bash_login)
(default: ~/.bashrc)
-f, --file FILE Set the name of the file to be used to store the
parked directory references (default: .pd-data)
--func FUNC_NAME Set the command name (default: pd)
-i, --import FILE Initialize the list of parked directories with those in FILE
--verify Look for the installation components of Park Directories
and report on the health of the installation.
The default behavior is to append the bootstrap code in your $HOME/.bashrc
script. This code checks that the executable, pd.sh, exists and runs it. If you'd like to have this code appended to another one of the profile scripts, use the -p, --profile
flag:
# Put the bootstrap code in .bash_profile
$ ./install.sh -p ~/.bash_profile
The executable and data file (defaults: pd.sh and .pd-data) are placed in your $HOME
directory, by default. Some might find it cleaner to place both in a different directory, maybe in $HOME/pd
or in $HOME/local/bin
, perhaps. Whatever your fancy, use the -d|--dir
option to choose where you'd like the files placed. The entire directory tree will be created automatically if it doesn't exist.
# Put the executable and data file in $HOME/scripts/pd
$ ./install.sh -d $HOME/scripts/pd
The function name, pd by default, becomes a part of your environment every time your terminal loads. With a short name like pd, it is possible to collide with another piece of software, function, or alias with the name pd. In addition to being the initials of the name of the software (park directories), pd was also chosen because the letters are typed from both hands, making it convenient and comfortable to type over and over. You might like to use kd, for example, because it keeps your hands on the home keys. Or maybe you use a different keyboard layout or speak a different language where a different mnemonic makes sense. For these reasons, among others, you can choose the name of the function by using the --func
option. Unlike creating an alias, this sets the name in the script that is registered in the environment.
# Set active function name to kd
$ ./install.sh --func kd
The default name of the file used to store the nickname and full path pairs is .pd-data. If you'd like to pick a different name for that file, use the -f|--file
option. There is rarely a strong need for this, as choosing a custom location solves most concerns, but if, for example, you prefer to call the file .savedDirs, you can. Please note that the option only takes the name of the file, NOT a full path.
# Store the parked directory mappings in a file named .savedDirs
$ ./install.sh -f .savedDirs
The data file is empty by default. You can use an exported list of parked directories to initialize the data file by using the -i|--import FILE_PATH
option.
Let's say you were working on a project on one VM or container or host and had a set of directories parked that were useful for that project. Then you need to move to a different system to continue working on your project, and you'd like to bring your parked directories with you.
# Export your parked directories list from Host 1
user@host1 $ pd -l
dev /home/user/docs/dev
proj /home/user/docs/dev/my-project
dbg /home/user/docs/dev/my-project/bin/debug/
rel /home/user/docs/dev/my-project/bin/release
user@host1 $ pd -e my-parked-directories.txt
List of parked directories exported to my-parked-directories.txt
# Transfer the exported file to Host 2
# Then install Park Directories and initialize the mappings
user@host2 $ ./install.sh -i my-parked-directories.txt
Installing Park Directories...
Checking for installed components...
Initiatlized data file with /home/user2/docs/my-parked-directories.txt
Installation complete!
Please execute the following command to use Park Directories:
source /home/user/.bashrc
user@host2 $ source /home/user/.bashrc
user@host2 $ pd -l
dev /home/user/docs/dev
proj /home/user/docs/dev/my-project
dbg /home/user/docs/dev/my-project/bin/debug/
rel /home/user/docs/dev/my-project/bin/release
user@host2 $
If you would just like to check that all the components of Park Directories are installed correctly, you can run ./install.sh --verify
. It will check for the components and report their status. The report for a proper installation looks like this.
$ ./install.sh --verify
Checking for installed components of Park Directories...
✔ Installation log file located @ /home/user/.pd.log
✔ Installation log file parsed.
✔ Executable @ /home/user/pd.sh
✔ Function active: pd
✔ Data file @ /home/user/.pd-data
✔ Bootstrap code located in /home/user/.bashrc
All components are installed as expected.
If components are missing, the report looks like this.
$ ./install.sh --verify
Checking for installed components of Park Directories...
✔ Installation log file located @ /home/user/.pd.log
✔ Installation log file parsed.
❌ Executable could not be located. Expected @ /home/user/pd.sh
✔ Function active: pd
❌ Data file could not be located. Expected @ /home/user/.pd-data
✔ Bootstrap code located in /home/user/.bashrc
Park Directories is only partially installed.
Please review the list above and refer to the README for possible solutions.
Use as Many Options as You'd Like
You can mix and match as many of the options as you'd like, where it makes sense. We can place the bootstrap code in $HOME/.bash_profile
, the executable in $HOME/savedDirs
, rename the data file .savedDirs, and use sd as the function name.
$ ./install.sh -p $HOME/.bash_profile -d $HOME/savedDirs -f .savedDirs --func sd
--verify
does not support any of the other options.
As new features are added, enhancements made, and bugs fixed, you'll want to update Park Directories without having to uninstall and re-install. Use the update.sh
script for all in-place updates. Here's the help text:
>>>> Update Park Directories <<<<
Perform an in-place update of Park Directories. If Park Directories
is not properly installed, the update will abort with information
about what needs to be fixed. It is also possible to change the name
of the command with --func or --func-only.
usage: update.sh [OPTIONS]
OPTIONS:
-h, --help Display this help message and exit
--func FUNC_NAME Update to the latest version and change the name
of the command to FUNC_NAME (default: pd)
--func-only FUNC_NAME Only change the name of the command to FUNC_NAME.
Does not execute any other update actions.
You can upgrade or downgrade Park Directories to the current version in the branch that you have checked out. If you'd like to checkout the latest version under development in a feature branch, you can checkout that branch and run ./update.sh
. If this latest version is not stable enough to leave it installed, you can return to the latest release by checking out the master branch and running ./update.sh
again. You can determine the current active version of Park Directories by executing pd --version
. You can determine the version in the branch you have checkout out by running ./pd.sh --version
.
# Determine the current running version
$ pd --version
Park Directories version 1.12.0
# Pull the latest updates from GitHub
$ git pull
<git output...>
# Checkout a feature branch
$ git checkout ftr_issue-56
# What version does this branch intend to release?
$ ./pd.sh --version
Park Directories version 2.0.0
# Upgrade to version 2.0.0
$ ./update.sh
Verifying current installation...
Park Directories is installed properly.
✔ Executable updated
Update complete.
Please restart your terminal or run the following:
source /home/user/.bashrc
# Source .bashrc and check new running version
$ source ~/.bashrc
$ pd --version
Park Directories version 2.0.0
# Something is not right, and you want to return to the stable version 1.12.0
# Checkout the master branch
$ git checkout master
# Downgrade to latest stable version 1.12.0
$ ./update.sh
Verifying current installation...
Park Directories is installed properly.
✔ Executable updated
Update complete.
Please restart your terminal or run the following:
source /home/user/.bashrc
# Source .bashrc and check new running version
$ source ~/.bashrc
$ pd --version
Park Directories version 1.12.0
$ ./update.sh
Verifying current installation...
✔ Installation log file located @ /home/user/.pd.log
✔ Installation log file parsed.
❌ Executable could not be located. Expected @ /home/user/pd.sh
✔ Function active: pd
❌ Data file could not be located. Expected @ /home/user/.pd-data
✔ Bootstrap code located in /home/user/.bashrc
Park Directories is only partially installed.
Please review the list above and refer to the README for possible solutions.
Cannot continue with update until Parked Directories is properly installed.
When you're ready to upgrade to a newer version of Park Directories, you might want to change the function name. Use the --func FUNC_NAME
option to perform an in-place upgrade and change the function name.
## Upgrade to the latest version and change the function name from pd to kd
$ ./update.sh --func kd
Verifying current installation...
Park Directories is installed properly.
✔ Function name changed to kd.
✔ Executable updated
Update complete.
Please restart your terminal or run the following:
unset -f pd
source /home/user/.bashrc
Do not forget to follow the instructions after the upgrade to either restart the terminal or to run
unset
and source your profile script.
You can change the function name without upgrading the application version by using the --func-only FUNC_NAME
option.
## Change the function name back to pd without updating the application version
$ ./update.sh --func-only pd
Verifying current installation...
Park Directories is installed properly.
✔ Function name changed to pd.
Please restart your terminal or run the following:
unset -f kd
source /home/user/.bashrc
Do not forget to follow the instructions after the upgrade to either restart the terminal or to run
unset
and source your profile script.
Park Directories is not a complicated application. A proper installation consists of the following:
- The executable
- The installation log file
- The data file
- Bootstrap code in a profile script
- The active function in the environment
You can try using uninstall.sh
to clean up. As described below, it will try to use the installation log file to remove a proper installation. It will also attempt to remove any of the components it can find through locating defaults and matching signatures. If the automatic uninstall does not clean things up for a fresh installation, then follow the instructions to perform a manual uninstall.
If you don't want to try to uninstall Park Directories and reinstall it to fix a broken installation, you can diagnose the problem and try to fix it manually with the following information.
Installation Log File
When Park Directories is installed, the installation details are stored in the installation log file. By default, this file is located at $HOME/.pd.log
. Its contents look like this:
path_to_executable /home/user/pd.sh
path_to_data_file /home/user/.pd-data
profile /home/user/.bashrc
func_name pd
It tells install.sh
, update.sh
, and uninstall.sh
- the location of the executable
- the location of the data file
- which profile script contains the bootstrap code
- and the name of the function that is registered in the environment.
These scripts create, modify, and remove the installation log file. Unless something has gone horribly wrong, this file should not be modified manually. However, if the application is saying that something is missing, it is because this log file is missing or includes the wrong information.
If the file is missing, but the rest of the application components are present, you can recreate the log file by copying the example file contents shown above and replacing the values to the right of the space with the proper information.
Executable
By default, the executable is called pd.sh
and is located in the user's $HOME
directory. If you believe that Park Directories is installed but pd.sh
is not in your home directory or at the location indicated in the installation log file, you can always search for it.
> find ~ -type f -name "pd.sh"
The installation script allows you to put the executable anywhere you'd like. If you can't find it, it is probably best to continue to clean up the rest of the application assets and reinstall. If your data file exists and you want to keep the current list of parked directories, you can rename the file (_e.g. .pd-data.bck) and use it with the -i, --import
option of the install.sh
script. You can also just leave it alone and reinstall. install.sh
does not overwrite the data file.
Data File
If the data file is not located where the installation log file says it should be, the active function will recreate the data file the next time you use it. If you know that the data file is somewhere else, you can either move it to where the installation log file says it should be or edit the log file with the correct location of the data file.
Profile Script
The installation log file records which profile script contains the bootstrap code. If the bootstrap code was moved manually to another profile script, you should update the log file with the correct location of the profile script. The proper way to change which profile script is used to bootstrap Park Directories is to uninstall it and reinstall it with the -p, --profile
option.
Active Function
By default, the active function is called pd
. The function name is set in the bootstrap code located in the profile script, default is $HOME/.bashrc
. The name of the function in pd.sh
and the name in the bootstrap code need to match. If they do not, for some reason, update the information in the bootstrap code to match what is in pd.sh
. Normally, uninstalling and reinstalling would fix this problem automatically.
I don't know why you'd ever want to uninstall Park Directories, but if you must... ;)
Just run ./uninstall.sh
.
There are no options for this command, but let's talk about what it will do in case something goes wrong. The command needs to
- remove the executable and data files
- remove the directory these are in, if it is empty
- remove the bootstrap code from the profile file
- remove
pd.log
.
If pd.log
exists and is not corrupted, everything will go smoothly. The script uses pd.log
to know
- where the executable and data files are located
- if we used a custom name for the data file
- in which profile script the bootstrap code was placed
- the name of the function.
If the executable and data files were placed in a custom directory and after removing them the directory is empty, uninstall.sh
will ask if you want to remove the directory.
When uninstall.sh
runs successfully, it will tell you that you can either restart your terminal or run unset -f {command_name}
to remove the command from your environment. This is not entirely necessary, but it is the last bit of housekeeping necessary.
If pd.log
is missing, the script will ask if it should attempt to uninstall using the default configuration. If you say, "yes", it will attempt to uninstall Park Directories as if it had been installed with the default configuration. If you say, "no", it will exit, and you will have to try and clean it up on your own. All hope is not lost, though. Run pd -h
(or use the custom command you chose). At the end of the help text, it tells you where the data file is located. That's where the executable is, too. Go delete them and the directory they are in, if it was a custom directory and is empty. The bootstrap code is most likey in $HOME/.bashrc
, most likely at the end. It's easy to find because the section begins with ## Parked Directories ##
, ends with ## End ##
, and is only 9 lines long. If pd.log
exists but is corrupt, delete it.
For more information about manual clean up, refer to the section Fixing Partial Installation.