after running a .sh file go back to the prompt i was before - linux

example.sh:
x=0
while true
do
x=$(expr $x + 1)
clear #to print no. # same location
printf "\n\n $x"|figlet -f block
sleep 1;
done
Like, htop/cmatrix/vim/nano/bashtop,etc...
After running it i have to get back to the last prompt,
not like, cat/find/,etc...
closest solution had come up with is to, run script inside a tmux session
what i mant was, i dont want to lose my command outputs i ran before,
like nano/vim/cmatrix it clears the screen then run it, then when we exit out of it like, ^c/q , we are back where we left the prompt, with the history[last ran commands and outputs]
is there a command which does this?
┌──(kali㉿kali)-[~]
└─$ vi
┌──(kali㉿kali)-[~]
└─$ nano
┌──(kali㉿kali)-[~]
└─$ cat copy
file contents
┌──(kali㉿kali)-[~]
└─$
Here, i opened nano, i opened vim, but u cant see my inside vim or nano , but thats not the case of cat, it just print it on the same session , with vim/nano/htop terminal is clean, thats not the case in sed/cat/ps
I wanted to create a script like that,[which will not effect the terminal session(like which run in another dimention)],
I tried reading the [bashtop][1] source code, which also have same behavior, but i couldnt find the code/command which does it

vim and less and many other tools access the terminal's alternate screen and then restore the original screen when they are done. You can use tput to access the alternate screen from your shell script:
#!/bin/sh
tput smcup # begin using the alternate screen
# ...
tput rmcup # stop using alternate screen (restore terminal to original state)
Note that you don't want to remain in the alternate screen when the script ends, so you may prefer to do:
#!/bin/sh
trap 'tput rmcup' 0
tput smcup

In bashtop, they had used tput on previous updates, then they changed it to,
#!/bin/sh
echo -en '\033[?1049h' #* Switch to alternate screen
# codes to run inside
echo -en '\033[?1049l' #* Switch to normal screen

Related

How to reset terminal without losing the current command?

I'm trying to create a keyboard shortcut to reset the current terminal.
I'm using a .inputrc entry like this:
"\C-K": 'echo -en "\\033c"\n'
It works, however, I can't do that while typing a command.
For instance, if I'm typing a command like this (with the cursor at the end):
$ foobar
and press CTRL+K, it will become
$ foobarecho -en "\033c""
and, of course, it is not going to work.
It is possible to do it?
I suppose it is possible, since that's what CTRL+L does.
The only problem with CTRL+L is that it won't clear the entire terminal, including history, just what's on screen.
I am not sure how to do that in inputrc, but you can do it with the bind command and its -x option.
bind -x '"\C-K": "echo -en \\033c"'
You can put the above line in your .bashrc and it will offer the same behaviour as the one you describe with CTRL+L.
do not understand "reset the current terminal". Clean your terminal? If so you can use command clear

How to run a specif .bashrc code only the first time konsole is opened

I have a chunk of code in my .bashrc, everytime one runs the shell (I usually use konsole) a switch case appears giving options of which branch or trunk to use. Example:
1) V0230
2) V0300
3) Dev
Enter Option: __
$PROJECT_HOME and others variables are set upon the choise made.
The annoying thing in this is that it appears everytime I open a new tab the same screen is printed.
But yet I want to open a new konsole and use a different branch, so, simple export a variabe can not be the solution
Must have a way to run this code only when a konsole new screen is open. Maybe making alias konsole=konsole --run <desired-function>. The konsole's documentation doesn't give a help, theres not even a man konsole just konsole --help.
Just create an alias:
$ alias konsole_select_branch='SELECT_BRANCH=true konsole'
and in your .bashrc:
if [ -n "$SELECT_BRANCH" ]
then
# select branch
fi
and use konsole or konsole_select_branch whether you want to choose a branch or just open a tab or window.
You could put a script in .bashrc which partly overwrite .bashrc; the zsh autocompletion facility does something similar, e.g. maybe do something like
if [ -f $HOME/.somebashthing; ]; then
. $HOME/.somebashthing
else
read SOMETHING
echo SOMEVAR=$SOMETHING > $HOME/.somebashthing
fi
This is only a sketch; it is up to you to fill the details.

How can I tell whether I'm in a screen?

When using screen in linux, how can I tell if I'm in a screen or not?
I could do exit and I'll exit a screen if I was in one, but if I wasn't, then I'll end up closing my terminal.
When doing screen -r, I could see if I have other screens attached, but how do I know if my current terminal is one of those attached screens?
Check $STY. If it's null, you're on a "real" terminal. If it contains anything, it's the name of the screen you're in.
If you are not in screen:
eric#dev ~ $ echo $STY
eric#dev ~ $
If you are in screen:
eric#dev ~ $ echo $STY
2026.pts-0.ip-10-0-1-71
Another way I've done it is to echo $TERM.
$ echo $TERM
screen
Since I end up doing this a lot, I added an alias into my .bashrc file:
alias trm='echo $TERM'
This way, whether in screen or not, if I just execute 'trm' it will show me whether I'm in SCREEN or elsewhere (usually XTERM).
Alternative approach to check if you are in screen.
type:
Ctrl-a ?
If you see the screen help you are in screen.
Otherwise you'll get a question mark '?' on the prompt.
Since all of the other methods here rely on environment variables (which can simply be overridden) or the command character for screen (which can also be overridden), the most foolproof way to check would be to list all the ancestors of the current process.
pstree --show-parents -p $$ | head -n 1 | sed 's/\(.*\)+.*/\1/' | grep screen | wc -l
If it prints 1, then the current process you're running has an ancestor with the word 'screen' in the executable's name, otherwise there wasn't.
A more facile visible inspection might be obtained from:
pstree --show-parents -p $$ | head -n 1 | sed 's/\(.*\)+.*/\1/' | less
My solution to the problem is a lot simpler: just hitting TAB makes the full terminal blink (a quick video inversion) if you are inside GNU Screen.
Tested working on most Linux (Ubuntu, Kali, Debian, RaspBerry... etc) and FreeBSD, GUI and any terminal, local or remote, including CtrlAltFn ones.
As an exception for this method, please, note this (rather complex, but possible) case scenario:
1.- SSH into computer A (lets assume Linux).
2.- Enter a new screen -S AScr from remote terminal on computer A.
3.- SSH from GNU Screen AScr terminal into Computer B.
4.- Enter a new screen -S BScr from remote terminal on computer B.
You are inside a Screen on cases 2 and 4, and outside a Screen on cases 1 and 3, but the terminal will blink on cases 2, 3 and 4.
While ssh'd into a remote (older) system I noticed that $TERM indicated I was using 'screen-256color', however there was no termcap/terminfo entry for that, so I was forced to resort to the following in .bashrc to prevent the terminal from producing occasional garbage:
case $TERM in
(screen-256color) export TERM='screen'
esac
to get it to use the plain entry instead.
TL;DR, $TERM will usually indicate if you are in a screen session when ssh'd remotely. You can use case $TERM in (screen*) echo "you are in a screen session"; esac if you just want a visual clue and don't need to do something specific
Add one or more of the followings into your .bashrc
alias mysession='echo ${STY}'
alias myterm='echo ${TERM}'
alias isscreen='if test -n "$STY"; then echo " screen session: ${STY}"; else echo " NOT a screen session"; fi'
Then you can know if you are inside a screen by typing simple commands.
The problem with most of the above answers is that we might be in a subshell of an attached screen session. Or we might be opening a shell to a remote host from within a screen session. In the former case, we can walk the process tree parentage and match for the screen program name. In the latter case, most of the time, we can check the TERM variable for something like screen*.
My answer os similar to /u/Parthian-Shot but not so dependent on the pstree utility; the options he use are not available to me. On the other hand, my implementation is still Linux-dependent: for non-Linux systems, one must tweak the ps command; for systems with older shells that don't support arrays, you'll have yet more work-arounds. But anyway:
ps_walk_parents() {
local tmp
local ppid=$PPID
while [[ $ppid != 1 ]]; do
tmp=($( ps -o ppid,comm -p $ppid ))
ppid=${tmp[0]} # grab parent pid
echo ${tmp[1]} # output corresponding command name
done
}
if [[ "$TERM" =~ screen* ]] || ps_walk_parents |grep -qxi screen ; then
# we are in a screen terminal
fi
We could optimize our function a bit to stop searching if/when a process parent matches the target command name ("screen"), but in general, the function will only hit 2 to 3 iterations. Presumably you want to put this code in some startup initialization such as .bashrc or .profile or something, so again, not worth optimizing.
screen -ls can tell you.
Outside screen:
$ screen -ls
There are screens on:
16954.pts-1.auds916 (Detached)
242.pts-8.auds916 (Detached)
2 Sockets in /tmp/screens/S-glennj.
Inside a screen:
$ screen -ls
There are screens on:
16954.pts-1.auds916 (Attached)
242.pts-8.auds916 (Detached)
2 Sockets in /tmp/screens/S-glennj.

Bash: call script with customized keyboard shortcuts?

Lets say I have a script, "myscript.sh", with contents being simply echo $PWD. I'd like to bind somehow this script to a key combo in bash (gnome-terminal) - so that when I press this key combination, the output of "myscript.sh" is inserted ("pasted") at the cursor position in the terminal.
Apparently, bash history and line manipulation is handled by readline - and the references I got for bash keyboard shortcuts, do reference readline:
bash keyboard shortcuts
Bash Reference Manual: Bindable Readline Commands
I've also seen in Bash Reference Manual: Readline Init File Syntax that the key bindings for bash can be listed by using bind -p (see help bind [not 'man bind'] for more). So maybe this question would better be titled as "_binding macros to custom keyboard shortcuts in readline" :) But in any case, is what I want possible to do?
I guess an alternative would be to have the script be something like "pwd | xsel -b", and then I call it on terminal - and I can paste afterwards; but I'd still like a single keyboard shortcut instead, say like Ctrl-Alt-H (which seems to be not used for anything), which will immediately insert/paste script output when pressed.
Thanks in advance,
Cheers!
EDIT: Just to clarify - here is my use case where I'd like this facility. I'm usually cd'd in a project folder, usually named something like myproject-folder-0012a, which is under revision control by svn. And there is a bunch of these folders. So quite often, I do commits where the first word of the message is the directory name, as in:
svn ci -m "myproject-folder-0012a: here a commit message"
But that is what I don't like - first I type 11 characters, which go rather fast:
svn ci -m "
And then, I cannot use autocompletion to get the name (i'm inside the folder) - which means I either have to fully type it (no way :)), or I copy paste it from the prompt (which requires selection - press mouse, drag, release mouse; then Ctrl+Shift+C, and then Ctrl+Shift+V, plus any left/right keys if I miss allignment - plus deletions and such if I make the copy wrong).
Meaning - so much work, just to get the bloody folder name for a bloody commit message :( I'd MUCH rather press something like (say) Ctrl-Alt-H, and have the folder name automatically inserted at cursor position, and be done with it :)
My suggestion for xsel is only because I could put it into a "global" script - say symlink it as /usr/bin/myscript (and obviously, the contents of the script are echo $(basename $PWD) rather than just pwd for my needs), and then I could do:
$ myscript # this puts directory name in clipboard
$ svn ci -m "[CTRL+SHIFT+V TO PASTE HERE]myproject-folder-0012a[NOW TYPE]: here a commit message"
... which sort of makes the workload less, but still - then I have to remember what the script name is, and call it, before I type the svn command (and I don't always remember that)... And still - I have to call a command, and then press a key combo; why shouldn't I just press a key combo once, and be done with it ??! :)
Well, hope this clarifies my problem a bit better ....
EDIT2: However, another reason why a bash keyboard shortcut would be useful, is that then I could also "paste/insert current directory name" not only in shell commands - but also in terminal programs, say like nano (where it would, arguably, be more difficult to use bash script or function expansion directly).
Simple version:
This command at a shell prompt:
bind '"\ee": "${PWD##*/}\e\C-e"'
or this line added to your ~/.inputrc:
"\ee": "${PWD##*/}\e\C-e"
will cause Alt-e to insert the basename of the current directory on the command line. It requires that the default binding of the readline function shell-expand-line which is \e\C-e be present (this could be adapted if it's different). I'm also making the assumption that you're using Bash's emacs mode.
Unfortunately, it causes things that have already been typed to be expanded as well. One of the affects of this is that after having typed:
svn ci -m "
and pressing Alt-e, the quotation mark will have disappeared. There are a couple of ways to deal with this.
One, assume that all you'll lose is the quote and either manually add it back or have the readline macro add it for you:
bind '"\ee": "${PWD##*/}\e\C-e\eb\"\C-e"'
which just isn't very satisfactory.
Advanced version:
Or, two, kill the line, do the insertion, then yank the line back:
bind '"\ee": " \C-u \C-a\C-k${PWD##*/}\e\C-e\C-y\C-a\C-y\ey\b"'
or
bind '"\ee": " \C-u \C-a\C-k${PWD##*/}\e\C-e\C-y\C-a\C-y\ey\b\ef\C-f"'
This leaves the rest of the line intact (nothing else is expanded or deleted), but it uses the kill ring, so it may leave it in a state that's different than you expect (if you're using it). It also inserts a space after the inserted directory name (the spaces in the macro are used to ensure that older kill-ring contents are not regurgitated if the macro is executed at the beginning or end of the line). The macro should work regardless of the position of the cursor in the line. The insertion will be made at the cursor's position, leaving the cursor in the same position [in the first version].
Edit: The second version leaves the cursor after the dirname and space that are inserted.
Edit 2:
The readline function shell-forward-word (unbound) does a better job than forward-word (\ef) for this. You can make use of that like this:
bind '"\ew":shell-forward-word'
bind '"\ee": " \C-u \C-a\C-k${PWD##*/}\e\C-e\C-y\C-a\C-y\ey\b\ew\C-f"'
By the way, you should know that Bash keyboard shortcuts are not active in other programs such as nano.
Ok, not really an answer, but I'd just like to summarize the comments I got so far, which are useful for my problem. However, the question as it stands - in respect to bash keyboard shortcuts running arbitrary scripts - is still not answered (I'd still prefer doing all this with a single key combo :))
First, I can use a 'global' script like:
$ sudo bash -c 'cat > /usr/bin/bpwd <<EOF
#!/bin/bash
basepwd=\$(basename \$(pwd))
echo -n \$basepwd # suppress line ending
# exec 1>/dev/null # debug: redir stdout to null
echo -n \$basepwd | xsel -i -b # suppress LF, and make xsel read from stdin
# exec 1>/dev/tty # debug: restore stdout
EOF
chmod +x /usr/bin/bpwd'
Or, I can add bash functions to my .bashrc (note: make sure you reload bash after you add these lines to .bashrc - for example, simply by typing bash in your current terminal):
$ echo '
bpwd2() { basepwd=${PWD##*/} ; echo -n $basepwd | xsel -i -b ; echo -n $basepwd ; }
svnci-test() { echo -n "$(bpwd2): $*" ; }
svnci-m() { svn ci -m "$(bpwd2): $*" ; }' >> ~/.bashrc
Basically, I misunderstood Reese Moore's suggestion originally - you can indeed use backticks - consider this command session (after the above commands have been ran):
$ bpwd
Desktop\
$ bpwd2
Desktop\
$ echo `bpwd`
Desktop
$ echo "`bpwd2` 2"
Desktop 2
This is what I needed to understand Moore's "the output from the backticked commands will be used as input on the executed command" (however, one also needs to take care to clean the line endings from the output); or, in my case, I can call
svn ci -m "`bpwd`: my message here"
# svn ci -m "${PWD##*/}: my message here" # alternatively
... or, I could follow camh's suggestion, and use svnci-m as a function (in my case, I almost never use additional arguments to svn ci, and so my version is slightly different). And to test whether arguments are passed correctly, I can use the svnci-test function:
$ svnci-test "my message"
Desktop: my message\
Thanks for the comments so far,
Cheers!
One way to do what you want with a single key press is to take advantage of programmable completion in bash. You possibly have some programmable completion set up with the bash_completion tool/package. If not, look into that to see the specifics of how it is done.
The idea is to have the programmable completion recognise when you have hit at the start of a svn commit message and then have it return a single completion which is the text you want to insert (the basename of the current directory).
I've only dabbled with programmable completion so I can't give you the details, but the above-mentioned bash_completion package or the subversion completion script may be a good start.

How do I launch an editor from a shell script?

I would like my tcsh script to launch an editor (e.g., vi, emacs):
#!/bin/tcsh
vi my_file
This starts up vi with my_file but first displays a warning "Vim: Warning: Output is not to a terminal" and my keystrokes don't appear on the screen. After I kill vi, my terminal window is messed up (no newlines), requiring a "reset". I tried "emacs -nw", "xemacs -nw", and pico with similar results. "xemacs" works but launches a separate window. I want to reuse the same terminal window.
Is there a way to launch an editor from a script so that it reuses the same terminal window?
I answered my own question! You have to redirect terminal input and output:
#!/bin/tcsh
vi my_file < `tty` > `tty`
The reason you're getting the error is that when you start a shell in your environment, it's starting in a subshell that has STDIN and STDOUT not connected to a TTY — probably because this is in something like a pipeline. When you redirect, you're opening a new connection directly to the device. So, for example, your command line turns
$ vi < `tty` > `tty`
into
$ vi < /dev/ttys000 > /dev/ttys000
So you're not really using your old STDIN/STDOUT, you're creating two new files and mapping them to your vi process's STDIN/STDOUT.
Now, tell us what you're doing with this and we'll tell you how to avoid this kludge.
I wanted to do something similar. I wanted an alias that would find the last file I was working on, and open it in vi(1) for editing. Anyway, I couldn't figure out how to do it as a readable alias (in tcsh) so I just created an ugly shell script (csh because I'm old) instead:
#!/bin/csh
set DIR = "~/www/TooMuchRock/shows/"
set file = $DIR`ls -t $DIR | head -1`
set tty = `tty`
vi $file <$tty >$tty
(1) kraftwerk:bin> which vi
vi: aliased to /usr/local/bin/vim -u ~/.exrc
Absolutely. :-)
Write your script and have it call the EDITOR environment variable, which you will have set to "emacsclient". Then start up Emacs, execute M-x server-start, switch to a shell buffer (M-x shell) and execute your script. Emacsclient will pop up the thing to be edited and C-x # will act as a "done" command and take you back to your script with edits completed or aborted, as you choose.
Enjoy.
Edit: I meant to add that these days Emacs IS my terminal program. I have dozens of shell buffers and never have to worry about losing output and can use all the power of Emacs to manipulate and analyse the terminal output. And have Emacs scripts generate input to the shells. Awesome actually. For example, watching Tomcat output scroll by in a shell buffer while editing sources or processing mail or doing most any Emacs thing is very convenient. When a Tomcat stack trace appears I can quickly respond to it.
Had the same trouble with 'pinfo' in a shell script 'while' loop. The line can be used in the script, it uses 'ps' to find the tty of the current process number, "$$", and stores that tty in $KEY_TTY:
KEY_TTY=/dev/`ps | grep $$ | tr -s '[:blank:]' | cut -d " " -f 3`
Later in the script, just call the tty-only proggie, with $KEY_TTY as input, in my case it was:
pinfo -m $s $page < $KEY_TTY
For 'vi' it'd be:
vi $a < $KEY_TTY > $KEY_TTY
The advantage is that the script as a whole can still accept STDIN input, and 'vi' (or whatever) should work fine -- without having to remember to set any environmental variables before running the script.
Set your terminal tty to a variable, and then redirect the editor i/o through that variable.
In your script:
#!/bin/sh
ls | while read a; do vi $a < $MYTTY >$MYTTY; done
And then execute the script with:
$ MYTTY=`tty` ./myscript >/tmp/log
I was able to get the desired behavior under bash+Cygwin+Terminator:
#!/bin/bash
vim foo
Run the script, vim loads, no error messages, behaves as normal. There are undoubtedly dozens of variations between our setups, however, so I can't hazard a guess as to what makes the difference. I'm curious what it is, but you got it working, which is the important part.

Resources