quick and smart navigation between directories in

2019-07-21 12:55发布

问题:

I am working on multiple projects with similar structures and sub-directories. An example of the hierarchy would be something like this:

Where X is the project name and subdirectories Main, Libs, Lx and Mx are all the same for different projects. insteding of cd'ing betweeing ong paths, I would like to create an alias (or a simple command) to jump to a directory (eg:Libs/ M2) regardless of the project name and the sub-directory that I am in (whether I am in L1 or L8, or project_red or project_yellow, I want to jump to M2).

This is easy to do by creating an alias for a single project:

alias goM2='cd /projects/project_red/Libs/M1/M2'

But I am not sure how to do this for all different project names. I can create multiple aliases but I was wondering if there is a neat way to do this. Perhaps by parsing the current directory to extract the project name and add the desired destination at the end but I am not sure how to do this.

Thanks

回答1:

To move between directories within the same project (and assuming that Main and Libs are the only direct children of the project root) something like this function should work.

projcd() {
    projdir=$PWD # Save current directory.
    projdir=${projdir%/Main/*} # Pull off anything after "Main"
    projdir=${projdir%/Libs/*} # Pull off anything after "Libs"

    # Find the target directory by name (more than one match will fail later).
    tgt=$(find "$projdir" -name "$1")

    if [ -z "$tgt" ]; then
        echo "No directory found for $1." >&2
        exit 1
    fi

    relpath=$(sed -e 's#[^/]\+/\?#../#g' <<<"${PWD#$projdir/}")

    cd "$relpath/$tgt"
}


回答2:

If the substructure is the same for every project (differing only in the number of libs and mains under Libs and Main directories), assuming your projects directory is under your $HOME directory, and a projects directory tree like this:

projects/
|-- project1
|   |-- Libs
|   |   |-- M1
|   |   |-- M2
|   |   `-- M3
|   `-- Main
|       |-- L1
|       |-- L2
|       `-- L3
`-- project2
    |-- Libs
    |   |-- M1
    |   |-- M2
    |   `-- M3
    `-- Main
        |-- L1
        |-- L2
        `-- L3

a function (declared in your profile or whatever library you use to load during your bash sessions) like the following _go_to_project_dir will do the work as desire. Of course some variables have only an explanatory purpose and a lot of assumptions have been done according to your file system hierarchy.

_go_to_project_dir() {
  local projects_HOME="$HOME/projects" # this could be configured as needed

  local current_project_dir # this is only an auxiliar variable
  printf -v current_project_dir "%b" "${PWD%%/[(Libs)(Main)]*}" # printf -v will store the formated message into the variable following -v option
                                                                # '%%' will remove the longest occurrence of the following pattern '/[(Libs)(Main)]*' 
                                                                # from the 'PWD' variable using pathname expansion

  local current_project_name
  printf -v current_project_name "%b" "${current_project_dir#${projects_HOME}/}" # '#' will remove shortest occurrence of the following pattern 
                                                                                 # '${projects_HOME}/' from the 'current_project_dir' variable 
                                                                                 # using pathname expansion

  local dir_name="$1"                             # Directory where you want to go
  local project_name="${2-$current_project_name}" # this will store second parameter if provided or 'current_project_name' content elsewhere 

  local dir_type="${dir_name:0:1}"                # this will extract the first character from your directory name but you could select a different length to match your actual pattern names

  case ${dir_type} in # here we select the path according to the previously extracted directory type
    M )
      path_to_go="${projects_HOME}/${project_name}/Libs/${dir_name}"
    ;;
    L )
      path_to_go="${projects_HOME}/${project_name}/Main/${dir_name}"
    ;;
  esac

  cd "${path_to_go}" # And it's done
}

Of course you can extract dir_type in some different ways according to your directory name patterns, but the core idea remains the same.



回答3:

If the various L1, L2, M1, M2 were all distinct names, you could add the collection of directory paths to the CDPATH environment variable (rather than making aliases). The feature has been discussed several times, e.g.,. How to make a custom BASH function to cd into a certain directory with autocomplete



回答4:

alias subfolder name=" eval $\"cd /from root to projects folder path/` pwd | cut -d'/' -fn`/sub folder path into the respective project\""

1)eval command take arguments and constructs command of it.
2) pwd | cut -d'/' -fn is used to get current Project name. sub folder path name and root to projects folder path are constants here.n represents order of project folder from root directory
3) Each time if you executes alias for sub folder it fetches current project name and concatenate it to root to projects folder path and sub folder path name and cd command and then executes.

In your case command is
for e.g:Libs folder
alias Libs=" eval $\"cd /projects/\` pwd | cut -d'/' -f3\`/Libs\""



回答5:

You can try something like https://github.com/frazenshtein/fastcd and configure shortcuts if basic functional is not enough