5
\$\begingroup\$

I think many know the problem of working with multiple projects: private projects, company projects, probably even projects for multiple companies.

From day-one, I've always searched for better ways to handle all those projects on the file system level. I think I figured out a nice basic directory structure that works for me and my workflow:

~/code/$company_name/$project_name/[$application_name]

But, even with auto-completion and a $CODE var that pointed to ~/code, I had to type a lot more than I wanted when I had to switch between some projects.

So, for the sake of laziness (I also heard some smart guys call it "efficiency," but nah, I'm just lazy) and to learn a bit more about my shell, I decided to write a function that will do some of the work I'm not willing to do.

These were the functional requirements I defined for that function:

  • quickly cd into a project by given company and project name
  • possibility to add an optional application name for projects with multiple applications
  • possibility to pass a flag to create new project directories

Since I'm still a junior developer (1-year work experience, no degree, autodidact) and don't have much experience with shell-scripting, I'm pretty sure there is a lot to improve in my solution.

And since I'm always on the search for improvements, I decided to show my code to those of whom might be more experienced in this than me.

function pcd () {
  local create=false
  local target_dir="$HOME/code"
  local argument_count=$#

  local root
  local app_name
  local project_name

  # When first param is -c, set create flag to true and remove the param
  if [[ $1 == "-c" ]]; then
    create=true
    (( argument_count=argument_count-1 ))
    shift
  fi

  # the root (private, company1, company2, etc...)
  # I really would like to make that optional too, but
  # that would require 
  root=$1

  # $PROJECT_ALIASES is a associative array to map some
  # project aliases to their actual names, it's set globally
  # since it's used in other scripts to and maintained through
  # it's own script
  project_name=$PROJECT_ALIASES[$2]

  # if the passed project string wasn't an alias,
  # assume it was the raw project name
  if [[ ! -n $project_name ]]; then
    project_name=$2
  fi

  # the app folder (for multi application projects, optional)
  app_name=$3

  # validate required params
  if [[ ! (( -n $root && -n $project_name )) ]]; then
    echo "[ERROR] - Please pass at least a root dir and a project name" >&2
    return 1
  fi

  target_dir="$target_dir/$root/$project_name"
  if [[ -n $app_name ]]; then
    target_dir="$target_dir/$app_name"
  fi

  # When the create flag is true (-c), create target directory
  if [[ $create == true ]]; then
    mkdir -p $target_dir
  fi

  # Finally, cd to the targeted directory
  cd $target_dir
}
\$\endgroup\$
  • 1
    \$\begingroup\$ If you're looking to reduce typing, are you using tab completion? If the company is Acme and the project is FooBar, cd ~/c<tab>A<tab>F<tab> \$\endgroup\$ – glenn jackman Aug 4 '13 at 1:10
  • 1
    \$\begingroup\$ If you're looking for efficiency, and built in functionality, read up on the CDPATH environment variable. \$\endgroup\$ – scottbb May 3 '16 at 12:12
2
\$\begingroup\$

Remove unused variables

The variable argument_count is not used for anything, so you should remove it.

Simplify shell arithmetics

Instead of this:

(( argument_count=argument_count-1 ))

You could simplify using the postfix operator:

(( argument_count-- ))

Simplify condition

This condition can be written simpler:

if [[ ! (( -n $root && -n $project_name )) ]]; then

Like this:

if ! [[ -n $root && -n $project_name ]]; then

Note that you could also drop both of the -n flags there, the expression will still mean the same:

if ! [[ $root && $project_name ]]; then

For the same reason, I suggest to drop all the -n in all conditions.

Always double-quote path variables

At some places you did a good job double-quoting path variables:

  target_dir="$target_dir/$root/$project_name"
  if [[ -n $app_name ]]; then
    target_dir="$target_dir/$app_name"
  fi

At others you didn't:

  # When the create flag is true (-c), create target directory
  if [[ $create == true ]]; then
    mkdir -p $target_dir
  fi

  # Finally, cd to the targeted directory
  cd $target_dir

Make it a habit to double-quote path variables always.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.