Currently my Windows Git Bash shell prompt looks like this:
UserName#ComputerName Path (Branch)
When I echo $PS1, I get:
\[\033]0;$MSYSTEM:\w\007\]\n\[\033[32m\]\u#\h \[\033[33m\]\w$(__git_ps1)\[\033[0m\]\n$
In my .bashrc file I tried to update this like so:
PS1="\[\033[32m\]\w$(__git_ps1)\[\033[0m\]\n$"
What happens is that I lose the UserName#ComputerName which is what was intended. However for some reason, the $(__git_ps1) also disappeared.
When I however do it like this: PS1=${PS1:46} it works as expected.
My plan was to add some additional changes (replace a fixed path with nothing) so the substring method is less then optimal.
What's going on?
UPDATE:
When I execute the PS1="\[\033[33m\]\w$(__git_ps1)\[\033[0m\]\n$" in the shell directly, it also works as expected.
The problem is that due to the double quotes, $(__git_ps1) expands when you define the prompt rather than when the prompt is later drawn.
It works in the shell directly because by defining it again, you cause $(__git_ps1) to be expanded again for the directory you're in. If you change branch, you'll see that it's stuck.
The solution is to use single quotes so that $(__git_ps1) becomes a literal value in the prompt, to be evaluated later:
PS1='\[\033[33m\]\w$(__git_ps1)\[\033[0m\]\n$ '
Related
I'm trying to modify my bash prompt to include the current git branch. This is complicated by the fact that there is already a set of rules that determines what the prompt might be - whether it includes color text, whether the user is on xterm etc. ... so what I really want is to be able to combine the string representing the git branch, colors and all, with the previously set prompt.
But I can't even get the most basic implementation to work. The following includes several of my attempts as I try to simplify the script to eliminate possible problems.
# Add current git branch, if any
parse_git_branch() {
git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/(\1)/'
}
#PS1="\[\e[34m\]\$(parse_git_branch)\[\e[00m\]$PS1 "
#PS1 = "\$(parse_git_branch) $PS1 "
#PS1 = "\$(parse_git_branch) "
#PS1 = "$(parse_git_branch) "
PS1 = $(parse_git_branch)
Essentially they all produce the same message:
PS1: command not found
I'm sure I am missing something simple. Can anyone tell me what it is?
The error you get is because of the spaces surrounding =, as bash attempts evaluates PS1 as a command, and fails.
You can fix it by just removing the spaces. Here is a sample prompt that prints the current user and directory, along with the prompt:
export PS1='[\u#\h] \W :: $(parse_git_branch)> '
Note the single quotes - if you instead use double quotes, the parse_git_branch will be evaluated and will not update on every prompt. As an alternative to single quotes, you can escape the $ if you prefer.
If you want to update your existing prompt to also have the git branch, you can print the current value of the PS1 environment variable and modify it to suit your needs, finally adding the modified version in say your .bashrc file.
In case you're willing to use an existing solution, there's a Git prompt function already included in many Linux distros. How to use:
PS1=…'$(__git_ps1 " (%s)")'…
The mixed quotes are intentional, and the single quotes are necessary to make this run every time the prompt is displayed. Replace the ellipses with the rest of the prompt, such as '\$ '. If __git_ps1 isn't available out of the box see the full code for a cross-platform solution (works on at least Ubuntu and Arch Linux; should work on recent NixOS).
The " (%s)" part is the format string, that is, a space, open parenthesis (because I want to keep this info separate from the rest of the prompt), the prompt string, and close parenthesis. The %s is replaced by a repository state string, by default just the branch name. See the source code for options and their meanings.
I've been trying to customize my bash command prompt with a shell script for some time now, but haven't had much success with it.
I'm trying to turn the prompt into something like this, with the Pos variables being strings or bash commands I've defined into the code.
PS1="[$PosZero][$PosOne][$PosTwo][$PosThree]$"
One thing I've tried to do save the current command prompt to a variable, and try and see if I can edit the contents of the brackets somehow, like so:
DEFAULT=$PS1
But what I've been struggling with is trying to edit the custom command prompt after having applied one already. If I'm attempting to change just one bracket, I want all the other brackets to keep whatever contents they have at the time. Instead, they erase themselves unless I pass the same information into the variables in the script.
I've been trying to find a way to parse the DEFAULT value (with the contents of PS1 within) to take out the contents of the brackets and apply them to the Pos variables. But I do not know how to do this. Does someone know how?
I think, this is what you want:
$ PS1='[$PosZero][$PosOne][$PosTwo][$PosThree]$ ' #Note: Use single quotes here, or escape $ as \$
[][][][]$ PosZero=abcd
[abcd][][][]$ PosOne=pqrs
[abcd][pqrs][][]$ PosZero=1234
[1234][pqrs][][]$ PosTwo=xyz
[1234][pqrs][xyz][]$ unset PosZero
[][pqrs][xyz][]$ PosOne=
[][][xyz][]$
I am writing my own unix scripts so I want to add a new directory for Bash. I add sth in .bash_profile like this.
PATH="~/Documents:${PATH}"
export PATH
and in my ~/Documents, there is a file named test of which the content is
#!/usr/bin/env python3.5
print("hahahhah")
I also used
chmod 755 test
to make it executable.
But I cannot call it in terminal directly. ./test works as usual.
What went wrong?
After I change to
PATH="$HOME/Documents:${PATH}"
export PATH
nothing happens.
FDSM_lhn#9-53:~/Documents$ test
FDSM_lhn#9-53:~/Documents$ ./test
hahahhah
Solution:
The fundamental reason is that I have a command of the same name as default one, So it won't work any way! Changing name will be sufficient!
Tilde doesn't get expanded inside strings. So by quoting the right-hand side of the assignment you prevent it from being expanded and get a literal ~ in your PATH variable which doesn't help you any.
You have two ways to fix this:
Drop the quotes on the assignment (yes this is safe, even for $PATH values with spaces, etc.).
Use $HOME instead of ~.
I prefer the second solution but the first is entirely valid for this case.
Beware though that in places where you aren't doing a straight assignment you often cannot just drop the quotes and trying to use ~ will cause problems.
In which case you will end up finding a question like this with an answer like this and something ugly like this.
NOTE
I am using Windows 7. On installing msysgit and GitHub for Windows, I found that git bash can be called from the folders. I opened up the terminal and first thing I wanted was to change how it displays in the console.
Here is what echo $PS1 gave me:
\[\033]0;$MSYSTEM:\w\007 \033[32m\]\u#\h \[\033[33m\w$(__git_ps1)\033[0m\] $
I've been modifying my bash's PS1 for some time now, and know most of the content there is. But I have never ever seen $MSYSTEM before.
Google resulted in nothing except some results about using it to set $MSYSTEM=MINGW32 which of course isn't the case here.
So, what does MSYSTEM variable do? Also, when I create a file .bashrc and put this line there; the terminal now shows a blank-space just before my username. This is because of the empty space in this segment \007 \033 but it was absent before. Here are the screenshots when I use a custom .bashrc and when I don't:
Without bashrc
With bashrc
I know why the newline is absent from my customized terminal; but the questions are:
What is $MSYSTEM?
Why is the first blank-space space missing in first case?
It sets the Window title to the value of MSYSTEM variable. As far as the
space, it looks like you messed up the final newline, notice carefully
export PS1='\[\033]0;$MSYSTEM:\w\007
\033[32m\]\u#\h \[\033[33m\w\033[0m\]
$ '
in the variable above each start of a new line insert a literal newline
character into the PS1.
How to change the title of an xterm
It is fine to run
evince ./result/demo_1000000_10000*.ps
on a shell window. But when I put it into a scripts file, then run that file, it can not find all those files ./result/demo_1000000_10000*.ps... here * is meant to be a wildcard and following is the scripts.
evince ./result/demo_1000000_10000"*.ps"
So are there any changes that should be made when putting commands into scripts?
It should work the same way in a script or on the command line. The quotation marks prevent the wildcard from being expanded. Just remove them from the script. (Why did you add them in the first place?)
If the command runs from the prompt as shown, then it should also run from a shell script if the current directory of the invoking process is the same - with exactly the same notation. There is no reason to include quotes in the scripted version if you want it to do the same as the unscripted version. And if you ran the quoted version at the command line, it would fail the same as the quoted version in the scripted version does.
However, in a script, you do have to worry about whether the Postscript files you plan to work on are in the correct location. Sometimes, the script uses an absolute pathname, sometimes the script uses cd to change directory to the correct place, sometimes there's an argument or environment variable that locates the files.
So, if used carefully, you don't have to change anything for the script to work - but there are many ways you can prevent the script from working. One of those is by adding quotes around wildcard characters.