Home directory navigation in bash script - bash

I need a simple bash script function for .bashrc file to navigate to my home directory.
We use hg for all our work purpose in the directory and contains many streams.
/home/<username>/RelStream1/
/home/<username>/RelStream2/
/home/<username>/RelStream3/
/home/<username>/RelStream4/
For namesake i call this /home//RelStream1/ path as repo home.
Now for work purpose, i need to navigate to sub folders from my repo home path.
/home/<username>/RelStream1/pkgdir/appsdir/moduledir/submoduledir/....
After finishing work, i need to come back to home repo directory for compilation.
I have added alias like this, but still its painful to remember the path back.
alias ..="cd .."
alias ..2="cd ../.."
alias ..3="cd ../../.."
alias ..4="cd ../../../.."
alias ..5="cd ../../../../.."
Please note many repo home directories would be used at any point of time and hence setting aliases as alias rhome='cd /home/<username>/RelStreamX/' will have little use.
I just need a simple bash function to get back to repo home directory (current repo).
It has to get the current path and navigate my directory back to home repo directory
Ex1:
From: /home/<username>/RelStream1/pkgdir/appsdir/moduledir/submoduledir/
To: /home/<username>/RelStream1/
Ex2:
From: /home/<username>/RelStream3/pkgdir/appsdir/moduledir/submoduledir/micromodule/
To: /home/<username>/RelStream3/
Ex3:
From: /home/<username>/RelStream4/pkgdir/appsdir/
To: /home/<username>/RelStream4/
I have tried some methods in bash(beginner), but does not give expected results.
code:
repohome_func()
{
cwd=$(pwd)
echo "CurrPath:${cwd}"
sep="/"
//My plan is to search the cur path with "/" char up to 4 times,
//cut the front string and then execute that cmd.
}alias rhome=repohome_func

This should work for you:
function repohome() {
local repodir=${PWD/$HOME\/}
cd "$HOME/${repodir%%/*}"
}

This should make:
alias rhome="cd $(pwd | sed 's~/[^/]*~~4g')"
It gets the current path with pwd and replaces it to what is needed. As this is within $() then we cd there.
You need to remove all current path but the first three blocks. With this sed, we do that.
See an example with a file:
$ cat a
/home/myuser/myrepo1/asld/as/asdf/asdf/asdf
/home/myuser/myrepo2/asdf
/home/myuser/myrepo3/asld/as/asdf/f/asdf
/home/myuser/myrepo4/asld/as/asdf/
$ sed 's~/[^/]*~~4g' a
/home/myuser/myrepo1
/home/myuser/myrepo2
/home/myuser/myrepo3
/home/myuser/myrepo4
From what was commented below, it seems like that the solution was not working as an alias, but it does as a function. The hypothesis is that there must be some alias in either cd, pwd or sed that makes them work differently.
As aliases are bypassed by functions, using it that way mades it. Otherwise, it could also work by using \ before any command, so the command alias gets bypassed as well.
alias rhome="\cd $(\pwd | \sed 's~/[^/]*~~4g')"
More info:
Temporarily disabling an alias / quoting a word with a backslash
\curl … | bash … what's the slash for?.

If you add your home directory to the front of CDPATH, for example,
CDPATH=/home/<username>:.
then any relative path used with cd will be looked up first in your home directory before the current working directory. Then
cd Relstream1
will take you to /home/<username>/Relstream1 before ./Relstream1.

You might want to try the builtin commands pushd and popd. If you use pushd <dir> instead of cd <dir>, you can then use popd to return to the previous working directory.

Related

zsh prompt replace named directory with it's alias

As I understand, if you create an alias for a directory in your .zshrc file, that directory is now considered a "named directory". I could be mistaken there, so let me know.
Based on the documentation here, it sounds like if you use "%~" in your zsh prompt and the current working directory is a named directory, then the prompt should show the alias for the directory, rather than the full path (i.e. ~{alias}). This does not seem to be working for me currently and I'm having a hard time finding examples or posts regarding this.
In my .zshrc file I have an alias like repo = "~/src/apps/repo". My hope is that when I am in that directory, the zsh prompt would show ~repo, but it always shows the full thing.
Any help is greatly appreciated!
In zsh, you can add a named directory with hash -d repo=~/src/apps/repo (not an alias). Also, ~ isn't expanded inside quotes, so you should remove them or use $HOME instead.
hash usage: https://zsh.sourceforge.io/Doc/Release/Shell-Builtin-Commands.html#index-hash-1
Static named directories: https://zsh.sourceforge.io/Doc/Release/Expansion.html#Static-named-directories

STAR error - INPUT file error: could not open read file: Read1 [duplicate]

When creating filepaths and URLs, I noticed that many times the path starts with ./ or ~/.
What is the difference between filepaths that start with ./ and ~/?
What do each of them mean?
For the sake of completeness ...
Just path is a file or directory named path in the current directory.
./path is a file or directory named path in the current directory, with the directory spelled out. The dot directory . represents the current directory, and path is the name of the file or directory within this directory.
~/path is a shorthand for $HOME/path where $HOME is a variable which refers to your home directory. Typically your home directory will be somewhere like /home/you or /Users/you where you is your account name. (The command echo "$HOME" will display your home directory.) The expanded value is an absolute path (unless you have messed up the value of $HOME thoroughly), as indicated by the initial slash.
/path is an absolute path which refers to a file or directory named path which is in the root directory /. Every file on Unix is ultimately somewhere in the directory tree which starts with the root directory.
A file name which begins with $ includes the value of a shell variable in its name (like for example $HOME above); you have to know the value of that variable to determine whether it ends up containing a relative or an absolute path. Similarly, ~ at the beginning of a file name gets replaced ("expanded") by the shell to a different string, as outlined above.
(Technically, it's possible for a file name to begin with a literal dollar sign or tilde, too; you would then have to quote or backslash-escape that character to avoid having the shell expand it to something else. This is rather inconvenient, so these file names tend to be rare in practice.)
In the following exposition, we refer to the result of any such replacements, and ignore the complication of possible quoting.
Every file name which begins with / is an absolute path (aka full path) which explains how to reach a particular node starting from the root directory. For example, /var/tmp/you/reminder.txt refers to a file or directory reminder.txt (probably a file, judging from the name; but Unix doesn't care what you call your files or directories) which is in the directory you which is in the directory tmp which is in the directory var which is in the root directory.
Every file name which doesn't begin with / is a relative path which indicates how to reach a particular file or directory starting from the current directory. The special directory .. is the parent directory (that is, the directory which contains this directory) and the special directory . is the current directory. So path/there refers to the file or directory there inside the directory path in the current directory; and (hover the mouse over the gray area to display the spoiler)
there/.././and/back/.. is a (wicked complicated) way to refer to the directory and in the current directory, where we traverse the there directory and then move back to the current directory; then stay in the current directory; then refer to the directory back inside the directory and, but then move back to the parent directory of that, ending up with ./and.
In addition to ~/ for the current user's home directory, some shells and applications allow the notation ~them/ to refer to the home directory of the user account them. Also, some web server configurations allow each user to have a public web site in their directory ~/public_html and the URL notation http://server/~them/ would serve up the site of the user account them for outside visitors.
The current directory is a convenience which the shell provides so you don't have to type long paths all the time. You can, if you want to.
/bin/ls /home/you/Documents/unix-101/directories.txt
is a longwinded but perfectly valid way to say (assuming you are in your home directory),
ls Documents/unix-101/directories.txt
You could also say
cd Documents/unix-101
ls directories.txt
and until you cd again, all your commands will run in this directory.
See What exactly is current working directory? for a longer exposition of this related concept.
A "directory" is sometimes called a "folder" by people who are not yet old enough to prefer the former.
Tangentially, don't confuse the directory name . with the Bourne shell command which comprises a single dot (also known by its Bash alias source). The command
. ./scriptname
runs the commands from the file ./scriptname in the context of the current shell instance, as opposed to in a separate subshell (which is what just ./scriptname does). In other words, this command line invokes the dot command on a file scriptname in the dot directory.
The Bourne shell (and derivatives like Bash, Zsh, etc) use single quotes to prevent variable expansion and wildcard expansion, and double quotes to permit variable expansion, but inhibit wildcard expansion in a string. The quoting rules on Windows are different, and generally use double quotes to keep whitespace-separated values as a single string (and % instead of $ for variable substitutions).
./ means "starting from the current directory". . refers to the current working directory, so something like ./foo.bar would be looking for a file called foo.bar in the current directory. (As a side note, .. means refers to the parent directory of the current directory. So ../foo.bar would be looking for that file one directory above.)
~/ means "starting from the home directory". This could have different meanings in different scenarios. For example, in a Unix environment ~/foo.bar would be looking for a file called foo.bar in your home directory, something like /home/totzam/foo.bar. In many web applications, ~/foo.bar would be looking for a file called foo.bar in the web application root, something like /var/http/mywebapp/foo.bar.
./ is the current directory
~/ is the home directory of the current user
./ means that path is relative to your current position.
~/ means that path is relative to your home directory.
I will explain a simple example of it. As developers mentioned:
./ is current directory.
~/ is the home directory of the current user.
How both of the file path expressions can help us? Suppose you want to execute a script (.sh) and you're in the same directory where file exists then you can simply do it ./filename.sh
I mostly use ~/ to access my home directory files like .bashrc when I want to add any config in it. It's easier since the file path expression (for home directory) feels much easier and makes accessibility to the file from anywhere, without worrying about the path or changing the path.
. represents current directory
.. represents the parent directory
~ represents the home directory for the current user. Home directory is also represented by HOME env variable. you can do echo $HOME on the shell to see it.
These are generally used to specify relative paths. The / in the end of each notation is a separator that you can use when using these notations together.
Ex:
$ cd ../.. # Go 2 directories backwards
$ cd ~ # Takes you to $HOME directory
$ cd . # Does nothing :) As it literally means go to the directory that you are already present in.
$ cd ~/dir1 $ go to `$HOME/dir1`
On Unix, in any directory if you do ls -a you would see that . and .. will be mentioned (even for empty directory). Like mentioned, these have special meaning and are generated by default in Unix systems and are generally helpful to specify relative paths (i.e, path to a different directory relative to your current directory)
cd command is harmless. So, just play around by combining notations with cd command. You will eventually get a grip of them.

Adding shortcut(soft-link) of a directory to global PATH so that it can be accessed from everywhere

I'm trying to put all my symlinks in one directory (I'll call this symlinks directory). I've exported the path of that directory and put it in my .bashrc file. The symlinks to executable applications are running fine but I'm having hard time making symlinks for my directory. This is what I tried.
ln -s ~/mydir/ m
where m is supposed to be my symlink to mydir directory.
This works only when I'm inside symlinks directory. Trying cd m or even just m didn't work from outside that directory. I get:-
bash: cd: m: No such file or directory
Okay, so I thought maybe the PATH doesn't recognize directory paths. So I tried creating a bash script.
#!/bin/sh
cd ~/mydir/
Tried this, m...permission denied. Okay I thought and did chmod +x m to that file. And when I run that script like m then nothing. I tried ./m, still nothing.
I'm close to losing my mind to do such a simple task.
PATH is used to look for commands and I think a command ought to be a file or a symlink to a file.
So, cd m doesn't work as here the command is "cd" (not m). The lookup for "m" does not happen in PATH.
Just m does not work as the "m" found in PATH is a link to a directory and not a file. You can try creating another "m" which points to a file and put it in a directory later in the PATH and it will be recognized when you run just m.
The script you created does work, except that the cd now happens in a new shell and is lost at the end of the script. You can check this by putting an ls after the cd in your script.
There are a few ways to achieve what you want to do.
One option is to use the CDPATH variable. This is the search path for the cd command. Check man bash for details but basically, all you need to do is add your symlinks directory to CDPATH.
export CDPATH=~/symlinks:$CDPATH
cd m ## will cd to linked directory
Alternatively, you can create aliases or functions and put it in your .bashrc or another file which you then source.
alias m="cd ~/mydir"
m() {
cd ~/mydir
}
And now you can just type m to cd to mydir

How can I cd to an alias directory in the Mac OSX terminal

Is there a way to get into an alias directory from shell with the command "cd" ? It always returns that "htdocs" isn't a directory.
Edit: I made the shortcut with the OS GUI -> rightclicked the htdocs directory and chose "Alias..." (i'm using a german OS if it's not alias maybe it's called shortcut in english?) then i moved it to my home directory (because my terminal starts from there when i open it).
All i want is to open my terminal and type "cd htdocs" so that i can work from there.
you can make symbolic link to it.
ln -s EXISTING_PATH LINK_NAME
e.g.
ln -s ~/Documents/books ~/Desktop/
Reference
Enter into a directory through an alias in Mac OS X terminal
All i want is to open my terminal and type cd htdocs so that i can work from there.
The easier approach is probably to ignore the links and add the parent directory of your htdocs directory to the CDPATH environment variable. bash(1) will check the contents of the CDPATH environment variable when you type cd foo to find the foo directory in one of the directories listed. This will work no matter what your current working directory is, and it'll be easier than setting symbolic links.
If the path to your htdocs is located /srv/www/htdocs/, then you could use CDPATH=/srv/www. Then, cd foo would first look for /srv/www/foo/ and change to it if it exists; if not, then it would look for foo in the current working directory and change to it if it exists. (This might get confusing if you have multiple htdocs directories on your system; in that case, CDPATH=.:/srv/www would let you change into a child directory easily but still use the /srv/www/htdocs/ version if no ./htdocs directory is present.)
You can add the CDPATH=/srv/www line to your ~/.bashrc file so it works every time you start a terminal.
I personally use this to quickly work in the directory which is present deep inside one of my Volumes in my Mac.
Open your ~/.bash_profile, create an alias to the directory by adding this:
alias cdh="cd /Volumes/Haiku/haiku/src/apps/superprefs"
Save it, restart your terminal. Now on typing cdh in your terminal should change the working directory to the one mentioned as the alias.
I am not sure how OSX exposes Alias links but since you are using bash you can just create a variable in your .bashrc file.
On its own line put:
htdocs=YourDirectoryPath/
Once you have restarted bash you can just type cd $htdocs
There is a old hint on macworld to do this in a way that is integrated with BASH: Enable 'cd' into directory aliases from the Terminal
Plus, here is an answer that uses this solution on superuser.
You may be able to use osascript to do this -- this command seems to work:
cd "`osascript -e "on run aFile" -e "set aFile to POSIX file aFile as alias" -e "tell application "\""Finder"\"" to return POSIX path of ( ( original item of aFile ) as text ) " -e "end run" path_to_my_Finder_alias 2>/dev/null`"
Basically this command is running an AppleScript that finds the destination path of the argument (path_to_my_Finder_alias) in a subshell, then wraps it in double quotes, and changes the directory to it.
Maybe someone with a little more bash expertise can turn it into a bash alias or function.
try:
alias cdgo=`echo cd /root/go/`
cdgo will run, then get command "cd /root/go/" and enter, and it will change your directory in current terminal process
It works on my centos, no test with osx

Navigating to Commonly/Recently Used Dirs, in Terminal (Unix/OS X)

Would it be possible to save certain locations that I've used recently/commonly (like /folder/folder/folder/) so that I don't have to manually navigate through each dir between my current and destination dir?
Sort of like alt-tab, but for paths. I'm on OS X, but perhaps this can be done using basic Unix skills?
Thanks!
If you set up your shell to save commands history, using Ctrl+R hotkey may save you some time, which performs search of previously executed commands as you type. Another good thing to know is that most shells provide you with file/directory name completion if you press Tab key once/twice, which is also of great help.
EDIT: you can also make some symbolic links inside single (e.g. home) directory to quickly access directories. Use ln -s <path to target file/directory> <path to link> command. Target paths could either be relative or absolute.
One way that works in most shells (but is slightly different for different shells) is the directory stack. You can use pushd to push a directory, popd to pop the top directory from the stack, and dirs to move directories around and switch to directories in the middle of the stack. I just checked, and the man page for pushd on Mac OS X is useless; use the man page for your shell (likely bash) and search for pushd, etc. there.
In Bash, you can add directories to the CDPATH variable. If you try to cd to a directory that doesn't begin with a slash then the directories listed in CDPATH are searched for a matching destination.
In zsh there are a few options.
A shell can keep a stack of the most recent few directories you've cd'ed into if you use setopt AUTO_PUSHD. With completion set up (autoload -U compinit; compinit), type cd + and press tab, then you'll get a numbered list:
~% cd /Library
/Library% cd /System/Library
/System/Library% cd +
1 -- /Library
2 -- /Users/nicholas
So the most recent directory is +1, etc. (You can reverse this, as I do, with setopt PUSHD_MINUS so you use - instead of + and the most recent directory is -1).
Another option is directory hashing; you can create pseudo-"home directories" (~whatever). Some of mine, for example:
hash -d v=/Volumes
hash -d a=/Volumes/BanjoArchive
hash -d pep=/System/Library/Frameworks/Python.framework/Versions/Current
hash -d sp=$(print /Library/Python/*/site-packages(On[1]))
So I can just type cd ~pep or cd pep (if unambiguous) or even pep (if AUTO_CD is set). In situations other than cd, you can use the directory stack with ~ as well, e.g. ~+1 or ~-1.
zsh can even replace shell variables after a ~ with the AUTO_NAME_DIRS option, though I don't use it because it would clutter the variable list. Nevertheless, here's an example:
~%setopt AUTO_NAME_DIRS
~%v=/Volumes
~%cd ~v
~v%pwd
/Volumes
zsh also supports cdpath as one of the other answers mentions. For example, I have:
cdpath=($HOME /Volumes)
so I can just use the name of a mounted volume or directory in my home directory to cd to it.
I stumbled upon Z and it has solved all of my dir-navigating issues.
Either an alias (via placing it into your ~/.bashrc or ~/.profile depending on setup):
alias godocs='cd /home/me/my_docs`
or pushd/popd as #Jeremiah suggests.
Take a look at "Cd Deluxe" for a greatly improved "change directory" command: http://www.plan10.com/cdd/.

Resources