Save current directory in variable using Bash? - bash

What I'm trying to do is find the current working directory and save it into a variable, so that I can run export PATH=$PATH:currentdir+somethingelse. I'm not entirely sure if they have a variable that contains cwd by default.
How do I save the current directory in variable using Bash?

This saves the absolute path of the current working directory to the variable cwd:
cwd=$(pwd)
In your case you can just do:
export PATH=$PATH:$(pwd)+somethingelse

I have the following in my .bash_profile:
function mark {
export $1=`pwd`;
}
so anytime I want to remember a directory, I can just type, e.g. mark there .
Then when I want to go back to that location, I just type cd $there

current working directory variable ie full path /home/dev/other
dir=$PWD
print the full path
echo $dir

Your assignment has an extra $:
export PATH=$PATH:${PWD}:/foo/bar

for a relative answer, use .
test with:
$ myDir=.
$ ls $myDir
$ cd /
$ ls $myDir
The first ls will show you everything in the current directory, the second will show you everything in the root directory (/).

On a BASH shell, you can very simply run:
export PATH=$PATH:`pwd`/somethingelse
No need to save the current working directory into a variable...

One more variant:
export PATH=$PATH:\`pwd`:/foo/bar

You can use shell in-build variable PWD, like this:
export PATH=$PATH:$PWD+somethingelse

Similar to solution of mark with some checking of variables. Also I prefer not to use $variable but rather the same string I saved it under
save your folder/directory using save dir sdir myproject and go back to that folder using goto dir gdir myproject
in addition checkout the workings of native pushd and popd they will save the current folder and this is handy for going back and forth. In this case you can also use popd after gdir myproject and go back again
# Save the current folder using sdir yourhandle to a variable you can later access the same folder fast using gdir yourhandle
function sdir {
[[ ! -z "$1" ]] && export __d__$1="`pwd`";
}
function gdir {
[[ ! -z "$1" ]] && cd "${!1}";
}
another handy trick is to combine the two pushd/popd and sdir and gdir wher you replace the cd in the goto dir function in pushd. This enables you to also fly back to your previous folder when making the jump to the saved folder.
# Save the current folder using sdir yourhandle to a variable you can later access the same folder fast using gdir yourhandle
function sdir {
[[ ! -z "$1" ]] && export __d__$1="`pwd`";
}
function gdir {
[[ ! -z "$1" ]] && pushd "${!1}";
}

Related

Is it possible to CD into a file?

I find a list of files that I need to cd to (obviously to the parent directory).
If I do cd ./src/components/10-atoms/fieldset/package.json I get the error cd: not a directory:, which makes sense.
But isn't there a way to allow for that? Because manipulating the path-string is pretty cumbersome and to me that would make total sense to have an option for that, since cd is a directory function and it would be cool that if the path would not end up in a file, it would recursively jump higher and find the "first dir" from the given path.
So cd ./src/components/10-atoms/fieldset/package.json would put me into ./src/components/10-atoms/fieldset/ without going on my nerves, telling me that I have chosen a file rather than a dir.
You could write a shell function to do it.
cd() {
local args=() arg
for arg in "$#"; do
if [[ $arg != -* && -e $arg && ! -d $arg ]]; then
args+=("$(dirname "$arg")")
else
args+=("$arg")
fi
done
builtin cd ${args[0]+"${args[#]}"}
}
Put it in your ~/.bashrc if you want it to be the default behavior. It won't be inherited by shell scripts or other programs so they won't be affected.
It modifies cd's arguments, replacing any file names with the parent directory. Options with a leading dash are left alone. command cd calls the underlying cd builtin so we don't get trapped in a recursive loop.
(What is this unholy beast: ${args[0]+"${args[#]}"}? It's like "${args[#]}", which expands the array of arguments, but it avoids triggering a bash bug with empty arrays on the off chance that your bash version is 4.0-4.3 and you have set -u enabled.)
This function should do what you need:
cdd() { test -d "$1" && cd "$1" || cd $(dirname "$1") ; }
If its first argument "$1" is a directory, just cd into it,
otherwise cd into the directory containing it.
This function should be improved to take into account special files such as devices or symbolic links.
You can if you enter a bit longer line (or create dedicated shell script)
cd $(dirname ./src/components/10-atoms/fieldset/package.json)
If you add it in script it can be :
cd $(dirname $1)
but you need to execute it on this way:
. script_name ./src/components/10-atoms/fieldset/package.json
You can put this function in your ~/.bashrc:
function ccd() {
TP=$1 # destination you're trying to reach
while [ ! -d $TP ]; do # if $TP is not a directory:
TP=$(dirname $TP) # remove the last part from the path
done # you finally got a directory
cd $TP # and jump into it
}
Usage: ccd /etc/postfix/strangedir/anotherdir/file.txt will get you to /etc/postfix.

Bash go to level 1 subdir if inside parentsubdir

Okay,
I would like to do the following in the shell.
If I am in a subdir like css which is inside a subdir like mypage (e.g. projects/mypage/htdocs/css) I would like to go into the root dir of the project, which is mypage. I would like to write this as a function to us as a command. The only "fixed" value is projects.
So basically if I am within any subdir of projects in the shell and I type the command goroot (or whatever) I want the function to check if it is in fact inside a subdir of projects and if so, go to the current subdir.
E.g.
~/projects/mypage/htdocs/css › goroot [hit return]
~/projects/mypage > [jumped to here]
Is this at all possible and if so how could I achieve this?
Assuming I am understanding correctly, this should work:
goroot() { cd $(sed -r 's#(~/projects/[^/]*)/.*#\1#' <<< $PWD); }
This sed command effectively strips off everything after ~/projects/SOMETHING and then changes to that directory. If you're not in ~/projects/ then it will leave you in the current directory.
Note: this assumes that $PWD uses the ~ to denote home, if it is something like /home/user/ then amend the sed command appropriately.
projroot=/home/user/projects
goroot() {
# Strip off project root prefix.
local m=${d#$projroot/}
if [ "$m" = "$d" ]; then
echo "Not in ~/projects"
return
fi
# Strip off project directory.
local suf=${m#*/}
if [ "$suf" = "$m" ]; then
echo "Already in project root."
return
fi
# cd to concatenation of project root, and project directory (stripped of sub-project path).
cd "$projroot/${m%/$suf}"
}

Source bash script to another one [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Reliable way for a bash script to get the full path to itself?
I have bash script test.sh which use functions from another search.sh script by following lines:
source ../scripts/search.sh
<call some functions from search.sh>
Both scripts are located in git repository. search.sh in <git_root>/scripts/ directory, test.sh is located in the same directory (but, generally speaking, could be located anywhere inside <git_root> directory - I mean I can't rely on the following source search.sh approach ).
When I call test.sh script from <git_root>/scripts/ everything works well, but as soon as I change current working directory test.sh fails:
cd <git_root>/scripts/
./test.sh //OK
cd ..
./scripts/test.sh //FAILS
./scripts/test.sh: line 1: ../scripts/search.sh: No file or directory ...
Thus what I have:
Relative path of search.sh script towards <git_root> directory
What I want: To have ability to run test.sh from anywhere inside <git_root> without errors.
P.S.: It is not possible to use permanent absolute path to search.sh as git repository can be cloned to any location.
If both the scripts are in the same directory, then if you get the directory that the running script is in, you use that as the directory to call the other script:
# Get the directory this script is in
pushd `dirname $0` > /dev/null
SCRIPTPATH=`pwd -P`
popd > /dev/null
# Now use that directory to call the other script
source $SCRIPTPATH/search.sh
Taken from the accepted answer of the question I marked this question a duplicatre of: https://stackoverflow.com/a/4774063/440558
Is there a way to identify this Git repository location? An environment variable set? You could set PATH in the script itself to include the Git repository:
PATH="$GIT_REPO_LOCATION/scripts:$PATH"
. search.sh
Once the script is complete, your PATH will revert to its old value, and $GIT_REPO_LOCATION/scripts will no longer be part of the PATH.
The question is finding this location to begin with. I guess you could do something like this in your script:
GIT_LOCATION=$(find $HOME -name "search.sh" | head -1)
GIT_SCRIPT_DIR=$(dirname $GIT_LOCATION)
PATH="$GIT_SCRIPT_DIR:$PATH"
. search.sh
By the way, now that $PATH is set, I can call the script via search.sh and not ./search.sh which you had to do when you were in the scripts directory, and your PATH didn't include . which is the current directory (and PATH shouldn't include . because it is a security hole).
One more note, you could search for the .git directory too which might be the Git repository you're looking for:
GIT_LOCATION=$(find $HOME -name ".git" -type d | head -1)
PATH="$GIT_LOCATION:$PATH"
. search.sh
You could do this:
# Get path the Git repo
GIT_ROOT=`git rev-parse --show-toplevel`
# Load the search functions
source $GIT_ROOT/scripts/search.sh
How get Git root directory!
Or like #Joachim Pileborg says, but you have to pay attention that you must know the path of this one to another script;
# Call the other script
source $SCRIPTPATH/../scripts/search.sh
# Or if it is in another path
source $SCRIPTPATH/../scripts/seachers/search.sh
The Apache Tomcat scripts use this approach:
# resolve links - $0 may be a softlink
PRG="$0"
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`/"$link"
fi
done
PRGDIR=`dirname "$PRG"`
Any way, you have to put this snippet on all scripts that use other scripts.
For the people who would rather not use git's features for finding the parent directory. If you can be sure you'll always be running the script from within the git directory, you can use something like this:
git_root=""
while /bin/true ; do
if [[ "$(pwd)" == "$HOME" ]] || [[ "$(pwd)" == "/" ]] ; then
break
fi
if [[ -d ".git" ]] ; then
git_root="$(pwd)"
break
fi
cd ..
done
I haven't tested this but it will just loop back until it hits your home directory or / and it will see if there is a .git directory in each parent directory. If there is, it sets the git_root variable and it will break out. If it doesn't find one, git_root will just be an empty string. Then you can do:
if [[ -n "$git_root" ]] ; then
. ${git_root}/scripts/search.sh
fi
IHTH

How to change current working directory inside command_not_found_handle

I'm trying to write a not found handle in Bash that does the following:
If $1 exists and it's a directory, cd into it.
If $1 exists inside a user defined directory $DEV_DIR, `cd into it.
If the previous conditions don't apply, fail.
Right now I have something like this:
export DEV_DIR=/Users/federico/programacion/
function command_not_found_handle () {
if [ -d $1 ]; then # the dir exists in '.'
cd $1
else
to=$DEV_DIR$1
if [ -d $to ]; then
cd $to
echo `pwd`
else
echo "${1}: command not found"
fi
fi
}
And although it seems to be working (the echo pwd command prints the expected dir), the directory in the actual shell does not change.
I was under the impression that since this is a function inside my .bashrc the shell wouldn't fork and I could do the cd but apparently that's not working. Any tips on how to solve this would be appreciated.
I think what's going on is that the shell fork()s after setting up any redirections but before looking for commands, so command_not_found_handle can't affect the interactive shell process.
What you seem to want to do may partly possible using the autocd feature:
shopt -s autocd
From man bash:
autocd - If set, a command name that is the name of a directory
is executed as if it were the argument to the cd com‐
mand. This option is only used by interactive shells.
Otherwise, just create a function that you invoke by name that performs the actions you are trying to use command_not_found_handle for.
It won't change directies if you run this program as a script in your main shell because it creates a sub-shell when it executes. If you source the script in your current shell then it will have the desired effect.
~/wbailey> source command_not_found.sh
That said, I think the following would achieve the same result:
wesbailey#feynman:~/code_katas> cd xxx 2> /dev/null || cd ..; pwd
/Users/wesbailey
just replace the ".." with your env var defined directory and create an alias in your .bashrc file.
I've had the very same wish and the solution that I've been using for a while was opening a new tab in gnome terminal by issuing the command gnome-terminal --tab --working-directory="$FOLDER" from inside the command_not_found handle.
But today I've come up with a solution which is not tied to a specific terminal application, but has exactly the intended behaviour.
The solution uses the PROMPT_COMMAND, which is run before each prompt. The PROMPT_COMMAND is bound to a function responsible for checking for a file related to current shell, and cd'ing into the directory specified in that file.
Then, the command_not_found_handle fills in the file when a change in directory is desired. My original command_not_found_handle also checkout a git branch if the current directory is a git repository and the name matches an existing branch. But to keep focus on answering the current question, I've stripped that part of code.
The command_not_found_handle uses find for searching for the directory matching the given name and goes only 2 levels deep in the directory tree, starting from a configured list.
The code to be added to bash_rc follows:
PROMPT_COMMAND=current_shell_cd
CD_FILE="${XDG_CACHE_HOME:-$HOME/.cache}/bash-cd/$$.cd"
current_shell_cd() {
if [ -r "$CD_FILE" ]; then
local CD_TARGET="$( cat "$CD_FILE" )"
[ ! -z "$CD_TARGET" ] && cd "$CD_TARGET" 2>/dev/null
rm "$CD_FILE"
fi
}
command_not_found_handle () {
local COMMAND="$1";
# List folders which are going to be checked
local BASE_FOLDER_LIST=(
"$HOME/Desenvolvimento"
"/var/www/html"
"$HOME/.local/opt/"
)
local FOLDER=$(
find "${BASE_FOLDER_LIST[#]}" \
-maxdepth 2 -type d \
-iname "$COMMAND" -print -quit )
if [ ! -z "$FOLDER" -a -d "$FOLDER" ]
then
mkdir -p "$( dirname "$CD_FILE" )"
echo "$FOLDER" > "$CD_FILE"
else
printf "%s: command not found\n" "$1" 1>&2
return 127
fi
}

How to manage Long Paths in Bash?

I have a problem to manage long paths. How can I get quickly to paths like
/Users/User/.../.../.../.../.../Dev/C/card.c
I tried an alias
alias cd C='cd /Users/User/.../.../.../.../.../Dev/C'
but I am unable to do aliases for two separate words. I have long lists of Bash aliases and paths in CDPATH, so I am hesitating to make them more. How can manage long paths?
[Ideas for Replies]
The user litb's reply revealed some of my problems in the management. Things, such as "CTRL+R", "!-3:1:2:4:x" and "incremental search", are hard for me. They probably help in navigating long directories and, in the sense, management.
Using symlinks is probably the best idea; but you can do it even easier than dumping them all into your home directory.
As you mentioned, BASH has a feature called CDPATH which comes in really handy here.
Just make a hidden folder in your homedir (so it doesn't clutter your homedir too much):
$ mkdir ~/.paths
$ cd ~/.paths
$ ln -s /my/very/long/path/name/to/my/project project
$ ln -s /some/other/very/long/path/to/my/backups backups
$ echo 'CDPATH=~/.paths' >> ~/.bashrc
$ source ~/.bashrc
This creates a directory in your homedir called ".paths" which contains symlinks to all your long directory locations which you regularly use, then sets the CDPATH bash variable to that directory (in your .bashrc) and re-reads the .bashrc file.
Now, you can go to any of those paths from anywhere:
$ cd project
$ cd backups
Leaving you with a short CDPATH, no cluttering aliasses, and more importantly: A really easy way to navigate to those long paths from other applications, such as UI applications, by just going into ~/.paths or adding that directory into your UI application's sidebar or so.
Probably the easiest all-round solution you can have.
Consider using symbolic links. I have a ~/work/ directory where I place symlinks to all my current projects.
You may also use shell variables:
c='/Users/User/.../.../.../.../.../Dev/C'
Then:
cd "$c"
Create symlinks in your home directory (or somewhere else of your choosing)
ln -s longDirectoryPath ~/MySymLinkName
See man ln for more details.
Probably the easiest solution is to use:
alias cdc='cd /Users/User/.../.../.../.../.../Dev/C'
alias cdbin='cd /Users/User/.../.../.../.../.../Dev/bin'
alias cdtst='cd /Users/User/.../.../.../.../.../Dev/tst'
if you're only really working on one project at a time. If you work on multiple projects, you could have another alias which changed the directories within those aliases above.
So, you'd use something like:
proj game17
cdc
make
proj roman_numerals
cdbin
rm -f *
proj game17 ; cdc
Since this is a useful thing to have, I decided to put together a series of scripts that can be used. They're all based aroung a configuration file that you place in your home directory, along with aliases to source scripts. The file "~/.cdx_data" is of the form:
scrabble:top=~/dev/scrabble
scrabble:src=~/dev/scrabble/src
scrabble:bin=~/dev/scrabble/bin
sudoku:top=~/dev/scrabble
sudoku:src=~/dev/scrabble/src
sudoku:bin=~/dev/scrabble/bin
sudoku:data=~/dev/scrabble/data
and lists all the relevant projects (scrabble and sodoku in this case) and their directories (which may be different for each project, but have top, bin, src and data in this example).
The first action is to initialize stuff, so put:
. ~/.cdx_init
at the end of your .bash_profile and create the "~/.cdx_init" file as:
alias cdxl='. ~/.cdx_list'
alias projl='. ~/.cdx_projlist'
alias cdx='. ~/.cdx_goto'
alias proj='. ~/.cdx_proj'
This sets up the four aliases to source the files which I'll include below. Usage is:
cdxl - List all directories in current project.
projl - List all projects.
proj - Show current project.
proj <p> - Set current project to <p> (if allowed).
cdx - Show current project/directory and expected/actual real
directory, since they can get out of sync if you mix cd and cdx.
cdx . - Set actual real directory to expected directory (in other words,
get them back into sync).
cdx <d> - Set directory to <d> (if allowed).
The actual script follow. First, ".cdx_list" which just lists the allowed directories in the current project (pipelines are broken into multiple lines for readability but they should all be on one line).
echo "Possible directories are:"
cat ~/.cdx_data
| grep "^${CDX_PROJ}:"
| sed -e 's/^.*://' -e 's/=.*$//'
| sort -u
| sed 's/^/ /'
Similarly, ".cdx_projlist" shows all the possible projects:
echo "Possible projects are:"
cat ~/.cdx_data
| grep ':'
| sed 's/:.*$//'
| sort -u
| sed 's/^/ /'
In the meaty scripts, ".cdx_proj" sets and/or shows the current project:
if [[ "$1" != "" ]] ; then
grep "^$1:" ~/.cdx_data >/dev/null 2>&1
if [[ $? != 0 ]] ; then
echo "No project name '$1'."
projl
else
export CDX_PROJ="$1"
fi
fi
echo "Current project is: [${CDX_PROJ}]"
and ".cdx_goto" is the same for directories within the project:
if [[ "$1" == "." ]] ; then
CDX_TMP="${CDX_DIR}"
else
CDX_TMP="$1"
fi
if [[ "${CDX_TMP}" != "" ]] ; then
grep "^${CDX_PROJ}:${CDX_TMP}=" ~/.cdx_data >/dev/null 2>&1
if [[ $? != 0 ]] ; then
echo "No directory name '${CDX_TMP}' for project '${CDX_PROJ}'."
cdxl
else
export CDX_DIR="${CDX_TMP}"
cd $(grep "^${CDX_PROJ}:${CDX_DIR}=" ~/.cdx_data
| sed 's/^.*=//'
| head -1
| sed "s:^~:$HOME:")
fi
fi
CDX_TMP=$(grep "^${CDX_PROJ}:${CDX_DIR}=" ~/.cdx_data
| sed 's/^.*=//'
| head -1
| sed "s:^~:$HOME:")
echo "Current project is: [${CDX_PROJ}]"
echo "Current directory is: [${CDX_DIR}]"
echo " [${CDX_TMP}]"
echo "Actual directory is: [${PWD}]"
unset CDX_TMP
It uses three environment variables which are reserved for its own use: "CDX_PROJ", "CDX_DIR" and "CDX_TMP". Other than those and the afore-mentioned files and aliases, there are no other resources used. It's the simplest, yet most adaptable solution I could come up with. Best of luck.
Revisiting. Today I received this link from a social bookmarking site, then I immediately remembered this question:
Navigation with bm
We keep a simple, plain text bookmarks
file and use a tool called bm to do
the look-ups. The tool can also be
used to edit the bookmark index
dynamically as shown below where we
add the directories from the previous
example to the index.
Once i cd'ed into such a long directory, i have that in the history. Then i just type Ctrl-R for the "(reverse-i-search)" prompt and type in a few characters, like Dev/C that appear somewhere in the path, and it shows me the command what i issued back then and i can easily jump to it again.
That works pretty well in practice. Because it won't find an entry if you haven't typed that path for quite some time, which would mean doing work to make things easier probably wouldn't be worth the time. But it definitely will find it if you used it recently. Which is exactly what i need.
In some way, it's a self-organizing cache for long commands & path-names :)
You might want to consider using a script like this in your .bashrc. I've used it on a daily basis ever since I read that post. Pretty bloody useful.
The user jhs suggested Pushd and Popd-commands. I share here some of my Bash-scripts that I found in Unix Power Tools -book. They are very cool when your directories get a way too long :)
#Moving fast between directories
alias pd=pushd
alias pd2='pushd +2'
alias pd3='pushd +3'
alias pd4='pushd +4'
The command 'pushd +n' "rotates" the stack. The reverse command 'popd +n' deletes the n entry of the stack. If your stack gets too long, use 'repeat n popd'. For examle, your stack is 12 directories long:
repeat 11 popd
When you want to see your stack, write 'pushd'. For further reading, I recommend the book on pages 625-626.
In your .bashrc find PS1='${debian_chroot:+($debian_chroot)}[\033[01;32m]\u#\h[\033[00m]:[\033[01;34m]
\W[\033[00m]\$ '
and replace the \w with \W.I already have it changed here. This will only give you the main directory where you are working. You can get the full directory by typing pwd
There are fundamental well-known ideas, like creating aliases:
alias cdfoo="cd /long/path/to/foo"
and also "dropping pebbles"
export foo=/long/path/to/foo
and also making the above "project-based". I use 'ticket based' directories.
topdir=ticket_12345
alias cdfoo="cd home/me/sandbox/$topdir/long/path/to/foo"
export foo="/home/me/sandbox/$topdir/long/path/to/foo"
but beyond all this, sometimes it's just handy to jump back and forth to where you've been recently, using command-line menus. (pushd and popd are cumbersome, IMHO).
I use acd_func.sh (listed below). Once defined, you can do
cd --
to see a list of recent directories, with a numerical menu
cd -2
to go to the second-most recent directory.
Very easy to use, very handy.
Here's the code:
# Insert into .profile, .bash_profile or wherever
# acd_func 1.0.5, 10-nov-2004
# petar marinov, http:/geocities.com/h2428, this is public domain
cd_func ()
{
local x2 the_new_dir adir index
local -i cnt
if [[ $1 == "--" ]]; then
dirs -v
return 0
fi
the_new_dir=$1
[[ -z $1 ]] && the_new_dir=$HOME
if [[ ${the_new_dir:0:1} == '-' ]]; then
#
# Extract dir N from dirs
index=${the_new_dir:1}
[[ -z $index ]] && index=1
adir=$(dirs +$index)
[[ -z $adir ]] && return 1
the_new_dir=$adir
fi
#
# '~' has to be substituted by ${HOME}
[[ ${the_new_dir:0:1} == '~' ]] && the_new_dir="${HOME}${the_new_dir:1}"
#
# Now change to the new dir and add to the top of the stack
pushd "${the_new_dir}" > /dev/null
[[ $? -ne 0 ]] && return 1
the_new_dir=$(pwd)
#
# Trim down everything beyond 11th entry
popd -n +11 2>/dev/null 1>/dev/null
#
# Remove any other occurence of this dir, skipping the top of the stack
for ((cnt=1; cnt <= 10; cnt++)); do
x2=$(dirs +${cnt} 2>/dev/null)
[[ $? -ne 0 ]] && return 0
[[ ${x2:0:1} == '~' ]] && x2="${HOME}${x2:1}"
if [[ "${x2}" == "${the_new_dir}" ]]; then
popd -n +$cnt 2>/dev/null 1>/dev/null
cnt=cnt-1
fi
done
return 0
}
alias cd=cd_func
if [[ $BASH_VERSION > "2.05a" ]]; then
# ctrl+w shows the menu
bind -x "\"\C-w\":cd_func -- ;"
fi
This might also be a useful function to put in your .bashrc; it moves up either a number of directories, or to a named directory, i.e. if you're in /a/b/c/d/ you can do up 3 or up a to end up in a.
I have no idea where I found this; if you know, please comment or add the attribution.
function up()
{
dir=""
if [ -z "$1" ]; then
dir=..
elif [[ $1 =~ ^[0-9]+$ ]]; then
x=0
while [ $x -lt ${1:-1} ]; do
dir=${dir}../
x=$(($x+1))
done
else
dir=${PWD%/$1/*}/$1
fi
cd "$dir";
}
If you want to switch to zsh, this is very easy-- just use "alias -g" (global alias, i.e. an alias that works anywhere in the command, not just the first word).
# alias -g c=/my/super/long/dir/name
# cd c
# pwd
/my/super/long/dir/name
In bash, I think the closest thing you'll get to 'aliasing' style is to write a function:
function ccd {
case "$1" in
c) cd /blah/blah/blah/long/path/number/one ;;
foo) cd /blah/blah/totally/different path ;;
"multiword phrase") cd /tmp ;;
esac
}
This means using something other than "cd" as the command when you want a shortcut, but other than that, it's flexible; you can also add an "ls" to the function so that it always reminds you what's in the directory after you cd, etc.
(Note that to use a multiword argument as above, you need to quote it on the command line, like this:
ccd "multiword phrase"
so it's not really all that convenient. But it'll work if you need to.)
Based on Andrew Medico's suggestion, check out J
Look into pushd, which allows you to maintain a stack of directories which you can push onto, pop off of, or rearrange.
Check out autojmp or dirmarks
Management requires both fast creation and removal of directories. Create many directiories:
mkdir -p user/new_dir/new/_dir/.../new_dir
Remove recursively many directories (be very careful when you are in lower directories!):
rm -r dir/.../new_dir/
For further reading, the cheat sheet may help you:
http://www.scribd.com/doc/2082838/Bash-Command-Line-History-Cheat-Sheet
It contains some nuggets, but I find it rather hard to read. I cannot get commands, like Meta+>, working. They probably help you in navigating long directories.
I realize the question is pretty old, but none of the scripts out there satisfied me, so I wrote a new one.
Here's the requirements I had in mind:
1) Use only bash commands -- I intend to use this on many different unices -- Linux, cygwin, HP-UX, AIX, and a couple others, so I couldn't depend on grep being consistent. Luckily I do have bash everywhere I work.
2) Short code -- I wanted to be able to bind this to a key in GNU screen, and just hit that key to paste the script into the current bash shell I'm using, so that I don't have to setup bash profiles on every system I use. Anything super long would be annoying and take too much time to paste.
3) No file usage -- Don't want to be littering shared logons with random files.
4) Act just like "cd" in the normal case. Don't want to have to think about which command to use before I start typing.
5) Provide "up" usage like this answer: How to manage Long Paths in Bash?
6) Keep a list of recently used directories, and switch to the most recent.
Here's the script:
#Jump History - Isaiah Damron
function jfind() {
lp=${JNHIST//==${PWD}==/==}
lp=${lp%%${lp#==*$1*==}}
lp=${lp##${lp%==*$1*==*}}
lp=${lp//==/}
[[ -d "$lp" ]] && echo $lp && return 0
return 1;
}
function jadd() {
[[ -z "$JNHIST" ]] && export JNHIST='=='
[[ 3000 -lt ${#JNHIST} ]] && export JNHIST=${JNHIST:0:3000} && export JNHIST="${JNHIST%==*}=="
export JNHIST="==$PWD${JNHIST//==${PWD}==/==}"
}
function j() {
{ cd $* 2> /dev/null && jadd; } \
|| { cd ${PWD/$1*/}$1 2> /dev/null && jadd; } \
|| { jfind $1 \
&& { cd $( jfind $1 ) 2> /dev/null && jadd; } ; } \
|| cd $*
}
function jh() {
[[ -z "$1" ]] && echo -e ${JNHIST//==/\\n}
[[ -n "$1" ]] && jfind $1 && cd $(jfind $1) && jadd
}
Usage:
jh [parameters]
If called on its own, without any parameters, it outputs the current history list. If it has a parameter, then it searches through the history for the most recently used directory that contains the string $1, and cd's to it.
j {parameters}
Does cd parameters. If that fails, it checks if any of the parent directories of $PWD match $1, and cd's to it. If that fails, then it calls jh $1. If that fails, then it outputs the result of cd parameters
Note: I used '==' as an internal separator. Hopefully you don't have any directories that contain a '==', but if you do you'll have to change around the script. Just :%s/==/whatever/g

Resources