Edit - 06/08/23 - Original Question Kept Substantially the Same
Thanks to Charles Duffy for providing valuable feedback in comments. The original question occurs in the context of item 1. But based on the feedback it appears that item 2 is the better option for managing system administration tasks. I may open another question or perhaps post some information in my answer here when I finish my research into perl
and /etc/profile.d
.
- Original Question: How to search and replace literal strings in a file, such as
PS1=<string>
in a.bashrc
file, usingsed
,awk
, orperl
? - Better question: How to enable desired prompt behavior using script(s) stored in
/etc/profile.d
that automatically execute whenever a user logs in?
Goal is to automate custom bash prompt on Debian PC and DietPi (ARM) Linux systems. The custom prompt inserts a blank line, to separate commands from terminal output, and looks like this but with different colors:
root@dpiBox /root
#
user@dpiBox /home/user
$
where root@dpiBox is red; user@dpiBox is green; and the present working directory is always shown in blue.
When a new user
is created then a copy of /etc/skel/.bashrc
is placed in the user's home directory as /home/user/.bashrc
. The root user already has a copy made as /root/.bashrc
.
My original plan was to edit /etc/skel/.bashrc
via script before adding new users and to manually edit the /root/.bashrc
. But when root or any user log in this automatically executes scripts properly installed under /etc/profile.d
. Charles Duffy seems to be advising the use of this feature for better management of system administration challenges!
Relevant lines in default /etc/skel/.bashrc
and /root/.bashrc
and /home/user/.bashrc
# /root/bashtest (simulates default .bashrc)
# /etc/skel/.bashrc
# /root/.bashrc
# /home/user/.bashrc
#force_color_prompt=yes
if [ "$color_prompt" = yes ]; then
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi
Step 1 - Uncomment line to turn on color prompt:
force_color_prompt=yes
Step 2 - Replace old PS1 (above) with new PS1 (shown here) to customize bash prompt:
PS1='${debian_chroot:+($debian_chroot)}\n\[\033[01;32m\]\u@\h\[\033[00m\]\[\033[01;34m\] $(pwd -P) \[\033[00m\]\n\$ '
The code [01;32m\]
is green for /home/user/.bashrc
. Change this code to [01;31m\]
which is red for /root/.bashrc
.
Step 1 - sed: good result
/usr/local/bin/bashsed (development script to edit bashtest/.bashrc)
#!/bin/bash
# uncomment to force color prompt on
off="#force_color_prompt=yes"
on="force_color_prompt=yes"
sed -i "s|$off|$on|" /root/bashtest
sed
code works with double quotes or single quotes used to define on
and off
. The double quotes must be used in the sed command.
Step 1 - perl: good result
/usr/local/bin/bashperl (development script to edit bashtest/.bashrc)
#!/bin/bash
# uncomment to force color prompt on
perl -i.bak -pe 's/#force_color_prompt=yes/force_color_prompt=yes/' /root/bashtest
The i.bak
switch backs up /root/bashtest
as /root/bashtest.bak
then edits the file in place. This command can be used on the command line without using the i.bak
switch.
Step 2 - sed: Bad result for sed -i "s|$old|$new|" /root/bashtest
/usr/local/bin/bashsed (development script to edit bashtest/.bashrc)
#!/bin/bash
# replace old PS1 with new PS1
# old \[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\
# PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
old='\\[\\033\[01;32m\\]\\u@\\h\\[\\033[00m\\]:\\[\\033\[01;34m\\]\\w\\[\\033\[00m\\]\\'
# new \n\[\033[01;32m\]\u@\h\[\033[00m\]\[\033[01;34m\] $(pwd -P) \[\033[00m\]\n\
# PS1='${debian_chroot:+($debian_chroot)}\n\[\033[01;32m\]\u@\h\[\033[00m\]\[\033[01;34m\] $(pwd -P) \[\033[00m\]\n\$ '
new='\\n\\[\\033\[01;32m\\]\\u@\\h\\[\\033\[00m\\]\\[\\033\[01;34m\\] \$(pwd -P) \\[\\033\[00m\\]\\n\\'
sed -i "s|$old|$new|" /root/bashtest
Step 2 the code runs without error, but produces no results, when double quotes are used to define old
and new
. The code throws an error sed: -e expression #1, char 149: unterminated `s' command
when single quotes are used to define old
and new
.
Edit - 06/08/23 - Comments
Posted my solution to Step 2 using perl
call in a bash
script.
Based on feedback from Charles Duffy the perl
solution for Step 2 can be modified to use literal strings stored as bash environment variables. Relevant information is provided near the top of the page under this link:
https://mywiki.wooledge.org/BashFAQ/021
According to Charles Duffy scripts should run from /etc/profile.d
when a user logs in to better manage sysadmin tasks. I need to do more research to understand this feedback. Here are two links that might be helpful:
https://serverfault.com/questions/434321/when-are-scripts-inside-etc-profile-d-executed
https://unix.stackexchange.com/questions/64258/what-do-the-scripts-in-etc-profile-d-do
Links in Original Question
I have searched extensively, tried dozens of experiments in the context below, and I cannot make sense of these references:
https://linuxhint.com/replace_string_in_file_bash/
Why would sed have trouble seeing my PS1 prompt?
Replacement of PS1 variable in .bashrc using Sed or Perl
Regarding sed expression evaluation in shell
So I need to have my "sed" examined! I would not mind using awk if it does the job, but then I need to see the simple command structure, before inserting the literal strings. Otherwise I always mess up the syntax.