Bash $PS1 Trouble (ubuntu) - bash

So I have a script in my .bashrc for customizing my prompt (see below).
function git_unpushed {
brinfo=$(git branch -v)
if [[ $brinfo =~ ("[ahead "([[:digit:]]*)]) ]]
then
echo "Not Pushed: ${BASH_REMATCH[2]}"
fi
}
function git_untracked {
untracked=$(git clean --dry-run | wc -l)
if [ $untracked -gt 0 ]
then
echo "Untracked: "$untracked
fi
}
export PS1="\
$(
# last_result=$?
uid="$(id -u)"
host="\[\e[97m\]\H"
path="\[\e[94m\]\w"
# If root
if [ "$uid" = "0" ];
then
user="\[\e[95m\]\u"
symbol="\[\e[97m\]#"
else
# If not root
user="\[\e[96m\]\u"
symbol="\[\e[97m\]\$"
fi
# If Git Repo
if [ -d './.git' ];
then
unpushed=$(git_unpushed)
untracked=$(git_untracked)
branch=$(__git_ps1)
status=$(git diff --shortstat)
second_line="hi"
else
second_line=$path
fi
echo "\[\e[1m\]$user#$host\n$second_line\n$symbol: \[\e[0m\]"
)"
My Question: Why does the path not get replaced whenever I cd to a git repo? (it does if I start a bash prompt within the repo"
I am using Ubuntu 14.04
Update:
After lot of work getting it just right, he is my result: Custom $PS1
Thanks everyone who helped out!

Edit:
As #EtanReisner points out, your code should work as intended for all users by enclosing your command substitution in single quotes.
export PS1='\
$(
# last_result=$?
uid="$(id -u)"
host="\[\e[97m\]\H"
path="\[\e[94m\]\w"
# If root
if [ "$uid" = "0" ];
then
user="\[\e[95m\]\u"
symbol="\[\e[97m\]#"
else
# If not root
user="\[\e[96m\]\u"
symbol="\[\e[97m\]\$"
fi
# If Git Repo
if [ -d "./.git" ];
then
unpushed=$(git_unpushed)
untracked=$(git_untracked)
branch=$(__git_ps1)
status=$(git diff --shortstat)
second_line="hi"
else
second_line=$path
fi
echo "\[\e[1m\]$user#$host\n$second_line\n$symbol: \[\e[0m\]"
)'
Old Answer:
This is because what you want to happen is only running every time your ~/.bashrc gets sourced. To get it to run after every command you execute, you can create a function and set the environment variable PROMPT_COMMAND to that function.
Try this:
new_ps1 (){
export PS1="\
$(
# last_result=$?
uid="$(id -u)"
host="\[\e[97m\]\H"
path="\[\e[94m\]\w"
# If root
if [ "$uid" = "0" ];
then
user="\[\e[95m\]\u"
symbol="\[\e[97m\]#"
else
# If not root
user="\[\e[96m\]\u"
symbol="\[\e[97m\]\$"
fi
# If Git Repo
if [ -d './.git' ];
then
unpushed=$(git_unpushed)
untracked=$(git_untracked)
branch=$(__git_ps1)
status=$(git diff --shortstat)
second_line="hi"
else
second_line=$path
fi
echo "\[\e[1m\]$user#$host\n$second_line\n$symbol: \[\e[0m\]"
)"
}
PROMPT_COMMAND="new_ps1"

Related

Bash script that runs in repl.it gives syntax error when in git alias

I'm trying to write a bash script for a git alias, to automate something.
I've written the script in repl.it, and it works without issue. However when I've taken the script and put it into my .gitconfig, and reduced it to a single line I'm now getting syntax errors.
-c: line 0: syntax error near unexpected token `then'
This obviously isn't helpful at all since everything is on a single line.
Here is the script on one line as it exists in my git config
markaswip = "!f(){ fullBranchName='jm/branch/name'; IFS='/' read -r -a array <<< $fullBranchName; hasBranch=0; for element in "${array[#]}" do if [ "$element" = $"wip" ]; then hasBranch=1; fi; done; if [ $hasBranch = 1 ]; then echo "Has WIP tag already"; else appendedString=$(printf '%s/' "${newArray[#]}"); output=${appendedString%?}; echo $output; git branch -m ${commitmessage}; fi; }; f"
And here it is unrolled
f() {
fullBranchName='test/branch/name';
IFS='/' read -r -a array <<< $fullBranchName
hasBranch=0;
for element in "${array[#]}"
do
if [ "$element" = $"wip" ];
then
hasBranch=1;
fi;
done;
if [ $hasBranch = 1 ];
then
echo "Has WIP tag already";
else
newArray=( "${array[#]:0:1}" "wip" "${array[#]:1}" );
appendedString=$(printf '%s/' "${newArray[#]}")
#printf '%s/' "${newArray[#]}"
output=${appendedString%?}
echo $output;
#git branch -m ${commitmessage};
fi;
}
f;

Customize the different colors of files, folders, binaries in the ouput of ls command in zsh/MacOS

I just switched to zsh from bash on my MacOS 10.14.6 and want to know how to have the output of content of folder (e.g.. when typing ls command) in different color
For example if I type
[mymac#Documents]$ls
Folder1
File1.txt
#stuff
I would like the 3 output items to be in 3 different colors. How can I edit the .zshrc file accordingly?
EDIT
I tried the following command with the corresponding error output:
$ ls --color=auto
ls: illegal option -- -
usage: ls [-ABCFGHLOPRSTUWabcdefghiklmnopqrstuwx1] [file ...]
The same happend with $ alias ls='ls --color=always'
It worked with the following command but the color of the folders are dark blue and hence very difficult to read.
alias ls='ls -G'
I also saw those 2 other links but it didn't help:
SO question
Is there a way of manually define the colors?
EDIT 2
I found this piece of code that worked for me (from there)
COLOR_RED="\033[0;31m"
COLOR_YELLOW="\033[0;33m"
COLOR_GREEN="\033[0;32m"
COLOR_OCHRE="\033[38;5;95m"
COLOR_BLUE="\033[0;34m"
COLOR_WHITE="\033[0;37m"
COLOR_RESET="\033[0m"
#git_color
function git_color {
local git_status="$(git status 2> /dev/null)"
if [[ ! $git_status =~ "working directory clean" ]]; then
echo -e $COLOR_RED
elif [[ $git_status =~ "Your branch is ahead of" ]]; then
echo -e $COLOR_YELLOW
elif [[ $git_status =~ "nothing to commit" ]]; then
echo -e $COLOR_GREEN
else
echo -e $COLOR_OCHRE
fi
}
#git_branch
function git_branch {
local git_status="$(git status 2> /dev/null)"
local on_branch="On branch ([^${IFS}]*)"
local on_commit="HEAD detached at ([^${IFS}]*)"
if [[ $git_status =~ $on_branch ]]; then
local branch=${BASH_REMATCH[1]}
echo "($branch)"
elif [[ $git_status =~ $on_commit ]]; then
local commit=${BASH_REMATCH[1]}
echo "($commit)"
fi
}
#PS1='\[\033[01;32m\]\u\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]'
#PS1+="\[\$(git_color)\]" # colors git status
#PS1+="\$(git_branch)" # prints current branch
#PS1+="\[$COLOR_BLUE\]\[$COLOR_RESET\]\$ "
#export PS1
export LC_ALL=en_US.UTF-8
export CLICOLOR=1
export LSCOLORS=gxBxhxDxfxhxhxhxhxcxcx

CENTOS 7 - $PATH incorrect after installing jdk

I'm new with Linux OS and I have installed jdk on centos7.
Now each time I login, I get following error message:
/usr/libexec/grepconf.sh: line 5: grep: command not found
-bash: /home/centos/.bash_profile: line 13: syntax error near unexpected token `newline'
-bash: /home/centos/.bash_profile: line 13: `export PATH=$PATH:/opt/jdk1.8.0_192/bin:/opt/jdk1.8.0_192/jre/bin:/usr/local/sbin:/usr/sbin:/home/centos/.local/bin:/home/centos/bin:/usr/bin/grep>'
and all commands are "not found"
I find this post to update path:
https://unix.stackexchange.com/questions/302743/centos-7-all-command-not-found-except-cd
and I update path with this command:
PATH=/usr/local/bin:/usr/bin:bin
So now with
sudo nano /home/centos/ .bash_profile command I have following content in bash_profile file:
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
PATH=$PATH:$HOME/.local/bin:$HOME/bin
export PATH
export PATH=$PATH:/opt/jdk1.8.0_192/bin:/opt/jdk1.8.0_192/jre/bin:/usr/local/sbin:/usr/sbin:/home/centos/.local/bin:/home/centos/bin:/usr/bin/grep>
What is problem ? How can I solve the error described ?
1rst edit in order to answer #nautical questions:
Here the content of .bash_profile file :
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
PATH=$PATH:$HOME/.local/bin:$HOME/bin
export PATH
export PATH=$PATH:/opt/jdk1.8.0_192/bin:/opt/jdk1.8.0_192/jre/bin:/usr/local/sbin:/usr/sbin:/home/centos/.local/bin:/home/centos/bin:/usr/bin/grep
Here the content of grepconf :
#!/bin/sh
case "$1" in
-c | --interactive-color)
! grep -qsi "^COLOR.*none" /etc/GREP_COLORS
;;
*)
echo >&2 "Invalid / no option passed, so far only -c | --interactive-color is supported."
exit 1
;;
esac
2nd Edit in order to answer questions in comment :
here ldd /usr/bin/grep command output:
linux-vdso.so.1 => (0x00007fff769b8000)
libpcre.so.1 => /lib64/libpcre.so.1 (0x00007f0454df3000)
libc.so.6 => /lib64/libc.so.6 (0x00007f0454a26000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f0454809000)
/lib64/ld-linux-x86-64.so.2 (0x000055ce09e0c000)
Here the result of ls -l /lib64/ld*
[centos#serveur-1 ~]$ ls -l /lib64/ld*
-rwxr-xr-x 1 root root 163400 Jan 29 18:55 /lib64/ld-2.17.so
lrwxrwxrwx 1 root root 10 Feb 20 21:51 /lib64/ld-linux-x86-64.so.2 -> ld-2.17.so
And each time I logout, then I login,
I get always "command not found" except for some command like for example :
java -version
So each time I must type "PATH=/usr/local/bin:/usr/bin:bin/" (answer found on this site) and each time I type echo $PATH, the output is more and more complex :
[centos#serveur-1 ~]$ echo $PATH
$PATH:/opt/jdk1.8.0_192/bin:/opt/jdk1.8.0_192/jre/bin:/usr/local/sbin:/usr/sbin:/home/centos/.local/bin:/home/centos/bin:/opt/jdk1.8.0_192/bin:/opt/jdk1.8.0_192/jre/bin:/usr/local/sbin:/usr/sbin:/home/centos/.local/bin:/home/centos/bin:/usr/bin/grep
I suppose $PATH content is bad just after login.
So how can I solved it definitively ?
Third edit for #tripleee :
Here .bashrc file content :
[centos#serveur-1 ~]$ sudo nano /home/centos/.bashrc
GNU nano 2.3.1 File: /home/centos/.bashrc
# .bashrc
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
# Uncomment the following line if you don't like systemctl's auto-paging feature:
# export SYSTEMD_PAGER=
# User specific aliases and functions
It talks about /etc/bashrc, so this is its content:
[centos#serveur-1 ~]$ sudo nano /etc/bashrc
GNU nano 2.3.1 File: /etc/bashrc
# /etc/bashrc
# System wide functions and aliases
# Environment stuff goes in /etc/profile
# It's NOT a good idea to change this file unless you know what you
# are doing. It's much better to create a custom.sh shell script in
# /etc/profile.d/ to make custom changes to your environment, as this
# will prevent the need for merging in future updates.
# are we an interactive shell?
if [ "$PS1" ]; then
if [ -z "$PROMPT_COMMAND" ]; then
case $TERM in
xterm*|vte*)
if [ -e /etc/sysconfig/bash-prompt-xterm ]; then
PROMPT_COMMAND=/etc/sysconfig/bash-prompt-xterm
elif [ "${VTE_VERSION:-0}" -ge 3405 ]; then
PROMPT_COMMAND="__vte_prompt_command"
else
PROMPT_COMMAND='printf "\033]0;%s#%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOM$
fi
;;
screen*)
if [ -e /etc/sysconfig/bash-prompt-screen ]; then
PROMPT_COMMAND=/etc/sysconfig/bash-prompt-screen
else
PROMPT_COMMAND='printf "\033k%s#%s:%s\033\\" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOM$
fi
;;
*)
[ -e /etc/sysconfig/bash-prompt-default ] && PROMPT_COMMAND=/etc/sysconfig/bash-prompt-de$
;;
esac
fi
# Turn on parallel history
shopt -s histappend
history -a
# Turn on checkwinsize
shopt -s checkwinsize
[ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\u#\h \W]\\$ "
# You might want to have e.g. tty in prompt (e.g. more virtual machines)
# and console windows
# If you want to do so, just add e.g.
# if [ "$PS1" ]; then
# PS1="[\u#\h:\l \W]\\$ "
# fi
# to your custom modification shell script in /etc/profile.d/ directory
fi
if ! shopt -q login_shell ; then # We're not a login shell
# Need to redefine pathmunge, it get's undefined at the end of /etc/profile
pathmunge () {
case ":${PATH}:" in
*:"$1":*)
;;
*)
if [ "$2" = "after" ] ; then
PATH=$PATH:$1
else
PATH=$1:$PATH
fi
esac
}
# By default, we want umask to get set. This sets it for non-login shell.
# Current threshold for system reserved uid/gids is 200
# You could check uidgid reservation validity in
# /usr/share/doc/setup-*/uidgid file
if [ $UID -gt 199 ] && [ "`/usr/bin/id -gn`" = "`/usr/bin/id -un`" ];
then
umask 002
else
umask 022
fi
SHELL=/bin/bash
# Only display echos from profile.d scripts if we are no login shell
# and interactive - otherwise just process them to set envvars
for i in /etc/profile.d/*.sh; do
if [ -r "$i" ]; then
if [ "$PS1" ]; then
. "$i"
else
. "$i" >/dev/null
fi
fi
done
unset i
unset -f pathmunge
fi
# vim:ts=4:sw=4
It's quite difficult to understand this mechanism when you come from "Windows world"...
Solved by updating .bash_profile as following:
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
PATH=$PATH:$HOME/.local/bin:$HOME/bin:/usr/local/bin:/usr/bin:/bin:/opt/jdk1.8.0_192/bin:/opt/jdk1.8.0_192/jre/bin
export PATH
I'm new with Centos so I hope I will retrieve my 2 points (removed by negative vote):
I have edited my question and structured it in order to answer questions asked in comments
I have looked for answer (see link) but I don't understand all instructions so may be difficult to be clear

Underlining to bash prompt only when pwd changed

I want to underline to my bash shell prompt(=PS1) only when a current directory is changed.
I tried this.
At .bashrc file I wrote
DIR_CHANGED=
function cd {
builtin cd "$#"
DIR_CHANGED=1
}
function dir_ul {
# if $DIR_CHANGED is 1, draw underline
if [ x == x$DIR_CHANGED ]; then echo -en '\033[0;34m'; else echo -en '\033[4;34m'; fi
export DIR_CHANGED=''
}
export PS1='$(dir_ul)\w$(tput sgr0)$ '
But not worked.
How do I fix?
I hate to say it, but I'd call that a bash bug. Here's a workaround: use PROMPT_COMMAND to
copy $DIR_CHANGED and reset it, and in dir_ul refer to that saved copy. Minimal changes:
function dir_ul {
if [ x == x$DIR2 ]; then echo -en '\033[0;34m'; else echo -en '\033[4;34m'; fi
}
PROMPT_COMMAND='DIR2=$DIR_CHANGED;DIR_CHANGED='
Test this in your ~/.bashrc with a second shell:
PREV="$PWD"
PROMPT_COMMAND='[[ $PREV != $PWD ]] && PS1="$(tput smul)\w$(tput rmul)$ " && PREV="$PWD" || PS1="$(tput rmul)\w$ "'
The $(dir_ul) gets evaluated at the instance you set the PS1 variable, rather than being continuously updated.

Is it possible to make some shell calls automatically when entering a directory?

Just like a local .bashrc file, which is sourced every time I entered the directory.
How to make this work?
You can use an alias:
$ echo 'echo "execute something for $PWD"' > tests/.cdrc
$ _cd()
{
\cd $1
[ -r .cdrc ] && . .cdrc
}
this function first change to the dir specified as argument, check if the file .cdrc is readable and source it.
$ alias cd=_cd
Then
$ cd tests
execute something for /path/to/tests
bash and zsh (and probably many other shells) have a feature that allows you to run an arbitrary command before the prompt is displayed. You can use this to source a .dirrc file, and it won't break tab completion.
Here's how to do it in bash:
PROMPT_COMMAND='
if [ "${PREV}" != "$(pwd -P)" ]; then
if [ -r .dirrc ]; then
. ./.dirrc
fi
PREV=$(pwd -P)
fi
'
From the bash man page:
PROMPT_COMMAND: If set, the value is executed as a command prior to issuing each primary prompt.
This is how to do it in zsh (see the zshmisc man page):
precmd() {
if [ "${PREV}" != "$(pwd -P)" ]; then
if [ -r .dirrc ]; then
. ./.dirrc
fi
PREV=$(pwd -P)
fi
}

Resources