advanced unix command-line trick - linux

I want help regarding unix command line.
In command line if i type any command like date; konsole should automatically execute ls and than execute date.
example: if i type date
than interface should be like ls ; date.
I can do alias but i want not only for date for every other command also. even if i don't supply any command and press empty enter it should execute ls.
I tried confugiring in set prompt variable. but i didn't got it and the variable is not reloading automatically.

Are you using konsole as your terminal emulator and tclsh as your interactive shell? If so, the former is irrelevant and the latter is an interesting tool choice. More likely, you are running bash as your interactive shell, in which case you can simply add a trap on DEBUG. To test the behavior type:
trap ls DEBUG
After executing this in bash, in this shell only, ls will be executed before every command. If this is the behavior you want, set the trap in ~/.bashrc.
Note that this is bash specific. Other shells have different mechanisms for getting this behavior.

Related

How to identify which REPL is running in the terminal?

I am trying to have my terminal title change depending on what that specific window is doing. So far I have the following which will update based on directory and server.
function settitle() {
if [[ -z "$ORIG" ]]; then
ORIG=$PS1
fi
TITLE="\[\e]2;$*:$(dirs -0)\a\]" #dirs -0 is like pwd but with ~/ instead of /home/user/
PS1=${ORIG}${TITLE}
}
PROMPT_COMMAND="settitle local" # local is the server name in this case
Now, sometimes I'm in the PHP (php -a) or MySQL (mysql -u user -ppass) REPL, and I'd like the title to reflect that instead of just being whatever directory I launched the REPL from.
The best I can figure is getting the last command somehow, then figuring out what the first word is, and running an if check in settitle(). I've tried everything from here and here among other places, and while I can usually get part of it to work in the command line, non of it works in settitle(). For example.
local:~$ echo 'foobar'
foobar
local:~$ !:0
echo
# I add echo !:0 to settitle()
local:~$ source .bashrc
!:0
local:~$
A note: It should be "source", or at least "echo" from before. !:0 does not recognize itself as a command so it will repeat the last real command over and over. The "!:0" being echoed is a literal string, not the results of the command. Additionally, saving to a var does not work, and just putting the command without trying to echo/save the result gives !:0: command not found.
I don't want to make this an XY problem, so if I am barking up the wrong tree here at any step of the process, please let me know. The goal is to be able to change the title of my terminal window if I enter an REPL. How can I identify when a command will enter me into one?
Note that PROMPT_COMMAND and similar shell features are not relevant when you're in a different REPL; from the point of view of the shell, the entire REPL session is one single command. The shell prompt doesn't show up again until you exit that REPL, and that's the point at which PROMPT_COMMAND and friends are activated.
One thing you can do is alias the command you use to start the REPL so that it sets the title of the window first:
alias phpa='setttitle PHP; php -a'
alias mysqli=`settitle MySQL; mysql -u "$USER"'
or something like that.
The sequence goes like this:
PROMPT_COMMAND runs.
The shell prints its prompt.
You type the command to start a REPL
You are in the REPL. The prompt you see is printed by the REPL, not the shell, which is not involved at this point. The shell is just hanging out waiting for you to exit the REPL; it's not printing any prompts, so it's not ever running PROMPT_COMMAND.
You type commands in the REPL. No matter how many you run, it's part of a single session that the shell sees as a single command.
You exit the REPL.
PROMPT_COMMAND runs.
The shell prints its prompt.

How to use xdotool to open a new tab, switch to it and run commands in it

I am trying to write a bash script to automate running some commands. However some of these commands should be running in their own terminal tab.
So I use the following in my bash script to open a new tab:
xdotool key ctrl+shift+t
this does the job, but the next commands in my bash script are still executed in the previous terminal tab.
How can I make the new opened terminal tab active and run the next commands in this tab?
What Terminal Emulator are you using? It strongly depends on this.
In general, you could write the commands you want to execute in a shell script and tell your terminal emulator to execute the script once it has started.
Example with xterm:
echo '#!/bin/bash' > /tmp/thescript
echo 'ls -la' >> /tmp/thescript
chmod +x /tmp/thescript
xterm -hold -e /tmp/thescript
EDIT: I just saw that u asked for a way to achieve this with xdotool. So this answer might be invalid. Please tell me if so - then i'll delete it.
How are you using xdotool? It can be done with a chain, for example:
$ xdotool key "ctrl+shift+t"; xdotool type "ls"; xdotool key Return
If all you want is to run the commands in the background / in parallel, without synchronously waiting for each command to complete before the next begins, terminate them with an ampersand & to instruct the shell to do so.
Alternatively, you can execute the commands in their own subshells by surrounding each with parentheses ( ). If they are long running processes or you do not wish to pollute the original shell with their output, you can fork them off and capture their output to file with something like (setsid command 1>/path/to/log &).
If separate tabs is necessary requirement, you can use xdotool to key the switch-to-the-next-tab binding or similar, and then key the commands you must run in that tab.
Instead of sorting out that mess yourself, you could use a script from this answer by Jacob Vlijm, which wraps a windowed approach that uses xdotool and wmctrl to 'send' commands to different terminal windows. The script is written in python 3 but it can easily be rewritten for a shell environment of choice.
A more direct approach involves use of a TIOCSTI ioctl to inject characters into another terminal. According to the tty_ioctl manual page:
NAME
ioctl_tty - ioctls for terminals and serial lines
...
DESCRIPTION
The ioctl(2) call for terminals and serial ports accepts many possible
command arguments.
...
Faking input
TIOCSTI const char *argp
Insert the given byte in the input queue
...
Here are c and perl wrappers, and an example in python as referenced by this answer.

How to manually start interactive ksh, and have it execute $HOME/.profile on startup?

If I start ksh manually by typing
/usr/bin/ksh
in bash, then ksh starts in interactive mode. So far so good. But, since it isn't a login shell, it won't execute its $HOME/.profile, which I need it to do. I tried running
/usr/bin/ksh $HOME/.profile
but then it just executed .profile and exited back to bash, without going into interactive mode. I've tried using the -i flag to force ksh to go into interactive mode, but it doesn't seem to work when I also give it .profile to execute.
I am using ksh93 on Raspian Linux.
When you want the settings in .profile (or any other shellscript), make sure the file is processed in the current shell, not a subshell. Start the commandline with a dot.
. $HOME/.profile
This is not a login shell, just an environment with your .profile executed.
You can use $HOME/.kshrc just like .bashrc for Bash.

Get bash autocompletion printed by stdin write

I want to write a program that will print out the autocompletions of bash.
Basically I'm writting something into bash stdin with
childProc.stdin.write("./myfi")
And would like to receive autocompletion for it like "./myfile.txt"
But childProc.stdout is empty after childProc.stdin.write("\t") so there has to be some other way to trigger autocompletion.
Any ideas?
Command-completion in only enabled in interactive shells. Bash is interactive if:
Neither a script filename nor the -c option were specified when invoking bash, and
both stdin and stderr are attached to terminals (as determined by isatty()), or
bash was started with the -i flag.
In your case, stdin is clearly a pipe, which is not a terminal. So probably command completion has been disabled. But if it were enabled, you'd see the result on stderr not stdout.
So you could try supplying the -i command line option when starting your bash shell, or you could attach its stdin, stdout and stderr file descriptors to a pseudo-tty. In either case, what you will see coming back from bash will be intermingled with terminal control codes, so you'll probably want to set TERM to something basic (like dumb).
If you want to see the completions which bash might generate, you can use the compgen built-in. compgen does not know about the customized completion settings installed by the complete command, and it is not easy to get the environment set up correctly for the -F and -C function, but other than that you can probably get it to generate whatever completion lists you would like. See the Bash manual for detailed option documentation.
I've found an answer.
The thing that made it work was Pseudoterminal.
This module actually.
https://www.npmjs.com/package/pty.js-dl

VIM. Sending commands to the terminal?

I'm trying to configure vim as my primary coding program. I have figured how to compile single files, but when I go to execute the program from within vim, I keep getting a 127 error code. I have a aliased on my box to ./a.out, however when I issue the command :!a from vim, it doesn't work. :!./a.out does. Does anyone know why this is?
Aliases are defined in rc files that are sourced by interactive shell only and work only in interactive mode (vim does pass everything to shell, it never executes anything except the shell directly with fork+execve).
By default shell launched from vim starts in non-interactive mode hence bashrc is not read and no aliases are defined (though even if they were defined, they won’t be used in non-interactive mode). You may set
set shellcmdflag=-ic
, then shell will be launched in interactive mode and .bashrc file with your alias will be read.
Aliases are a feature of your shell (say, bash). ! operator directly executes a file - shell never sees it, and can't do alias expansion on it. (EDIT: See ZyX)
If you want to make executing your ./a.out easy, you can do something like:
command XX !./a.out
then you can do :XX. Or,
nnoremap X :!./a.out<CR>
then a single key X will suffice.
Another option (which is frowned upon for security reasons) is to add the current directory to your PATH:
PATH="./$PATH"
which will allow you to run your program with just a.out as opposed to ./a.out. If you then compile your program with (a language-dependent isomorphism of) -o switch, you can have it named just a:
gcc -o a foo.c
Given this, !a would work. Use at your own risk.
EDIT: ZyX is correct-er. :) I'll leave the answer here for the other information.

Resources