Identify gnome-terminal window by tab title - gnome-terminal

Assume the following:
I have multiple gnome-terminal windows open
each window has multiple tabs open
I know that I opened the file ".bashrc" in vim somewhere. So a tab with the
title ".bashrc (~) - VIM" is in one of the gnome-terminal windows. This tab
might or might not be active tab in the window.
Is there any way to identify the gnome-terminal window, that holds that tab
and to switch to it (preferably activating the tab)?
More general:
Is there any way to identify and activate a gnome-terminal window by the title of one of it's tabs?
or:
Is there any way to identify and activate a gnome-terminal window by the
program currently executed in on of its tabs?

Revisiting this question I found a solution (or hack) to get what I want.
Gnome Terminal implements the org.gnome.Shell.SearchProvider2 dbus interface. This interface can be used to search for terminal tabs that match a given term. By using a empty string as search term, all terminal tabs are matched and the ids are returned. With this ids it is possible to get the names (aka titles) of the tabs.
I hacked together the following script to collect the information and using fzf to select the tab I'm looking for. Than this tab is activated.
#!/bin/bash
# get UUIDs of all gnome-terminal tabs
get_term_ids()
{
# Call search with empty string ... will match all
dbus-send --session --dest=org.gnome.Terminal --print-reply=literal \
/org/gnome/Terminal/SearchProvider \
org.gnome.Shell.SearchProvider2.GetInitialResultSet \
array:string:"" \
| tail -n 1 | sed 's/^ *//;s/ *]$//;s/ */,/g'
}
# get "uuid term-title" list
get_term_titles()
{
ids="$(get_term_ids)"
dbus-send --session --dest=org.gnome.Terminal --print-reply=literal \
/org/gnome/Terminal/SearchProvider \
org.gnome.Shell.SearchProvider2.GetResultMetas \
array:string:${ids%,} \
| grep '^ *\(id\|name\) ' \
| sed -e '/^ *id /{N;s/^ *id *variant *\([^ ]*\) *)\n/\1/}' \
-e 's/ *name *variant */ /;s/ *)$//'
}
# activate a term identified via uuid
activate_term()
{
dbus-send --session --dest=org.gnome.Terminal --print-reply \
/org/gnome/Terminal/SearchProvider \
org.gnome.Shell.SearchProvider2.ActivateResult \
string:$1 array:string:'' uint32:0 >/dev/null
}
result="$(get_term_titles | fzf --with-nth 2..)"
if [ -z "$result" ]; then
exit 1
fi
activate_term "${result%% *}"

Related

How to get list of commands used in a shell script?

I have a shell script of more than 1000 lines, i would like to check if all the commands used in the script are installed in my Linux operating system.
Is there any tool to get the list of Linux commands used in the shell script?
Or how can i write a small script which can do this for me?
The script runs successfully on the Ubuntu machine, it is invoked as a part of C++ application. we need to run the same on a device where a Linux with limited capability runs. I have identified manually, few commands which the script runs and not present on Device OS. before we try installing these commands i would like to check all other commands and install all at once.
Thanks in advance
I already tried this in the past and got to the conclusion that is very difficult to provide a solution which would work for all scripts. The reason is that each script with complex commands has a different approach in using the shells features.
In case of a simple linear script, it might be as easy as using debug mode.
For example: bash -x script.sh 2>&1 | grep ^+ | awk '{print $2}' | sort -u
In case the script has some decisions, then you might use the same approach an consider that for the "else" cases the commands would still be the same just with different arguments or would be something trivial (echo + exit).
In case of a complex script, I attempted to write a script that would just look for commands in the same place I would do it myself. The challenge is to create expressions that would help identify all used possibilities, I would say this is doable for about 80-90% of the script and the output should only be used as reference since it will contain invalid data (~20%).
Here is an example script that would parse itself using a very simple approach (separate commands on different lines, 1st word will be the command):
# 1. Eliminate all quoted text
# 2. Eliminate all comments
# 3. Replace all delimiters between commands with new lines ( ; | && || )
# 4. extract the command from 1st column and print it once
cat $0 \
| sed -e 's/\"/./g' -e "s/'[^']*'//g" -e 's/"[^"]*"//g' \
| sed -e "s/^[[:space:]]*#.*$//" -e "s/\([^\\]\)#[^\"']*$/\1/" \
| sed -e "s/&&/;/g" -e "s/||/;/g" | tr ";|" "\n\n" \
| awk '{print $1}' | sort -u
the output is:
.
/
/g.
awk
cat
sed
sort
tr
There are many more cases to consider (command substitutions, aliases etc.), 1, 2 and 3 are just beginning, but they would still cover 80% of most complex scripts.
The regular expressions used would need to be adjusted or extended to increase precision and special cases.
In conclusion if you really need something like this, then you can write a script as above, but don't trust the output until you verify it yourself.
Add export PATH='' to the second line of your script.
Execute your_script.sh 2>&1 > /dev/null | grep 'No such file or directory' | awk '{print $4;}' | grep -v '/' | sort | uniq | sed 's/.$//'.
If you have a fedora/redhat based system, bash has been patched with the --rpm-requires flag
--rpm-requires: Produce the list of files that are required for the shell script to run. This implies -n and is subject to the same limitations as compile time error checking checking; Command substitutions, Conditional expressions and eval builtin are not parsed so some dependencies may be missed.
So when you run the following:
$ bash --rpm-requires script.sh
executable(command1)
function(function1)
function(function2)
executable(command2)
function(function3)
There are some limitations here:
command and process substitutions and conditional expressions are not picked up. So the following are ignored:
$(command)
<(command)
>(command)
command1 && command2 || command3
commands as strings are not picked up. So the following line will be ignored
"/path/to/my/command"
commands that contain shell variables are not listed. This generally makes sense since
some might be the result of some script logic, but even the following is ignored
$HOME/bin/command
This point can however be bypassed by using envsubst and running it as
$ bash --rpm-requires <(<script envsubst)
However, if you use shellcheck, you most likely quoted this and it will still be ignored due to point 2
So if you want to use check if your scripts are all there, you can do something like:
while IFS='' read -r app; do
[ "${app%%(*}" == "executable" ] || continue
app="${app#*(}"; app="${app%)}";
if [ "$(type -t "${app}")" != "builtin" ] && \
! [ -x "$(command -v "${app}")" ]
then
echo "${app}: missing application"
fi
done < <(bash --rpm-requires <(<"$0" envsubst) )
If your script contains files that are sourced that might contain various functions and other important definitions, you might want to do something like
bash --rpm-requires <(cat source1 source2 ... <(<script.sh envsubst))
Based #czvtools’ answer, I added some extra checks to filter out bad values:
#!/usr/bin/fish
if test "$argv[1]" = ""
echo "Give path to command to be tested"
exit 1
end
set commands (cat $argv \
| sed -e 's/\"/./g' -e "s/'[^']*'//g" -e 's/"[^"]*"//g' \
| sed -e "s/^[[:space:]]*#.*\$//" -e "s/\([^\\]\)#[^\"']*\$/\1/" \
| sed -e "s/&&/;/g" -e "s/||/;/g" | tr ";|" "\n\n" \
| awk '{print $1}' | sort -u)
for command in $commands
if command -q -- $command
set -a resolved (realpath (which $command))
end
end
set resolved (string join0 $resolved | sort -z -u | string split0)
for command in $resolved
echo $command
end

Open files in different split windows in VIM

I have some $somePaths array of 4 folders. I want to open some files from this folders in VIM. The following opens them in tabs.
vim -p `for i in ${somePaths[#];}; do echo $i/src/main.cpp; done`
Actually I'd like to have those files in split windows (cross-like). How it can be done?
Apart from -p, Vim also offers the -o and -O command-line arguments for horizontal / vertical splits. Unfortunately, they cannot be mixed. To build you own custom window layout, you have to pass the explicit window placement commands via -c. This example
$ vim 1 -c 'bel vsplit 2' -c '1wincmd w' -c 'bel split 3' -c '3wincmd w' -c 'bel split 4'
creates a layout that looks like this:
+-----------+-----------+
| | |
| | |
| | |
|1 |2 |
+-----------+-----------+
| | |
| | |
| | |
|3 |4 |
+-----------+-----------+
To keep passing the list of files as one block, you can use the fact that the buffer numbers increase monotonically, and refer to buffer numbers in the command:
$ vim -c 'bel vert sbuf 2' -c '1wincmd w' -c 'bel sbuf 3' -c '3wincmd w' -c 'bel sbuf 4' a b c d
vim has :vertical command, which could be useful in your case. give this a try:
vim +'vertical all' [your file list]
You can try using -O4 instead of -p.
The accepted solution posted above is good and solves your use case, however I would like to point out an alternate way of achieving something similar without much effort or configuration.
VIM has inbuilt support for record sessions, :h :mksession, what that allows you to do is save the current vim session (open files, splits, tabs, windows, etc, depending on the value of :h 'sessionoptions'. Although record and maintaining sessions can be slightly tedious, what I'd suggest is use either of xolox/vim-session (I've used it previously) or tpope/vim-obsession (use it now). That will allow you to re-open a session exactly as you left off!
Here is what I do, I have this snippet in my ~/.zshrc:
function vim() {
tmux rename-window "vim - ${PWD##*/}"
if test $# -gt 0; then
env vim --servername ${PWD##*/} "$#"
elif test -f ~/.vim/sessions/${PWD##*/}.vim; then
env vim --servername ${PWD##*/} -S ~/.vim/sessions/${PWD##*/}.vim
else
env vim --servername ${PWD##*/} -c Obsession\ ~/.vim/sessions/${PWD##*/}.vim
fi
}
What that does basically is check if vim is launched as it is without any arguments and checks if a session already exists & loads it, or using tpope/vim-obsession starts recording a new session, which will be loaded the next time you open vim. The session name is just the name of the directory you launch vim in. If you do pass any arguments to vim however it would behave like you'd expect and doesn't bother worrying about sessions.
This way, I can now just launch vim in any directory and first time I do so, it will start recording a new session, whereas on subsequent invocations it will load that session and tpope/vim-obsession keeps it updated.

Linux - Script to edit clipboard content

Is there a way to write a script that would be applied to the clipboard content ( I'm using Linux\Gentoo)?
When copy-pasting it would be nice to bind a keystroke that would (e.g -) remove all line breaks from the copied text.
I couldn't find where to start such a task (where should such a script be placed\how to reference the clipboard) so just a hint of where to start would be appreciated.
Thanks!
You need to install xsel to access your clipboard. Then you can just use a small script and piping. I use this to prepend four spaces to my current selection in order to get a version I can paste into StackOverflow editors:
xsel | while IFS='' read a; do echo " $a"; done | xsel
Default for xsel is to manipulate (or query) your PRIMARY selection (what you just marked with the mouse). You can use the clipboard (C-c, C-v stuff) instead by using the option -b.
To remove all line breaks from your current clipboard, just try this:
xsel -b | tr '\n' '\r' | sed 's/\r*//g' | xsel -b

What are the alternatives to wmctrl?

Do you know of any alternatives to wmctrl? A program that lets you manipulate windows and window management from the command line.
One drawback with wmctrl is that whilst you can manipulate the current window, you cannot get wmctrl to list information about the current window (it ignores -r).
To find the id of the currently active window, use:
xprop -root -f _NET_ACTIVE_WINDOW 0x " \$0\\n" _NET_ACTIVE_WINDOW | awk "{print \$2}"
Using this id, you can then get a lot of information about the currently active window:
xprop -id $(xprop -root -f _NET_ACTIVE_WINDOW 0x " \$0\\n" _NET_ACTIVE_WINDOW | awk "{print \$2}")
From there, you can grep what you need, or make it show just the desired field the same way I extracted _NET_ACTIVE_WINDOW above. So, to find the PID of the currently active window, you would append -f _NET_WM_PID 0c " \$0\\n" _NET_WM_PID to the command above, making it:
xprop -id $(xprop -root -f _NET_ACTIVE_WINDOW 0x " \$0\\n" _NET_ACTIVE_WINDOW | awk "{print \$2}") -f _NET_WM_PID 0c " \$0\\n" _NET_WM_PID | awk "{print \$2}"
Note that wmctrl also accepts the same kind of id in combination with the -i flag.
You can trick wmctrl into outputting the ID number of the active window by turning on verbose mode and telling it to move the active window with an invalid parameter:
wmctrl -v -r :ACTIVE: -e dummy
While this does exit with an error status, it also outputs the ID number of the active window:
envir_utf8: 1
Using window: 0x08400004
The -e option expects a list of comma separated integers: "gravity,X,Y,width,height"
Once you have the ID number of the active window, you can list all the windows and search for that ID number:
wmctrl -l
It's awkward to get information about the active window with wmctrl, but it's possible.
xdotool is a reasonable alternative (github project here), although unfortunately the author doesn't seem to care about it much any more.
My experience with wmctrl version 1.07 under RH Linux 5.5 and 5.6 64-bits is that
wmctrl gets completely lost at times. For instance, when looking for a firefox window
the following returns nothing:
% wmctrl -lpGx | grep -i 'Firefox'
My suspicion is that wmcntl cannot find firefox windows due to the nature of the window manager, in this case, metacity. This manager seems to reparent windows and perhaps this causes wmctrl not to list firefox windows. 'xwininfo' does list the firefox windows.
If you have access to xdotool (my version is 2.20110530.1) then you can try:
% mywin=`xwininfo -root -tree | awk '/- Mozilla Firefox/ { printf $1; exit}'`
% xdotool windowactivate --sync $mywin mousemove --window $mywin 0 0
This makes firefox active, makes it the top window in the stack on your desktop, and puts the mouse over it (as is sometimes needed when a user's environment sets focus to a window under the mouse without requiring a click.) If you don't want the mouse to move simply
remove 'mousemove --window $mywin 0 0' from the above.
Note: I had the same problem with finding Konqueror windows on the same Linux systems.
window id
wmctrl -a :ACTIVE: -v 2>&1 | grep "Using window: " | awk "{print \$3}"
You can check xdo which can do a decent job with minimal ressources.

Linux command to list all available commands and aliases

Is there a Linux command that will list all available commands and aliases for this terminal session?
As if you typed 'a' and pressed tab, but for every letter of the alphabet.
Or running 'alias' but also returning commands.
Why? I'd like to run the following and see if a command is available:
ListAllCommands | grep searchstr
You can use the bash(1) built-in compgen
compgen -c will list all the commands you could run.
compgen -a will list all the aliases you could run.
compgen -b will list all the built-ins you could run.
compgen -k will list all the keywords you could run.
compgen -A function will list all the functions you could run.
compgen -A function -abck will list all the above in one go.
Check the man page for other completions you can generate.
To directly answer your question:
compgen -ac | grep searchstr
should do what you want.
Add to .bashrc
function ListAllCommands
{
echo -n $PATH | xargs -d : -I {} find {} -maxdepth 1 \
-executable -type f -printf '%P\n' | sort -u
}
If you also want aliases, then:
function ListAllCommands
{
COMMANDS=`echo -n $PATH | xargs -d : -I {} find {} -maxdepth 1 \
-executable -type f -printf '%P\n'`
ALIASES=`alias | cut -d '=' -f 1`
echo "$COMMANDS"$'\n'"$ALIASES" | sort -u
}
There is the
type -a mycommand
command which lists all aliases and commands in $PATH where mycommand is used. Can be used to check if the command exists in several variants. Other than that... There's probably some script around that parses $PATH and all aliases, but don't know about any such script.
The others command didn't work for me on embedded systems, because they require bash or a more complete version of xargs (busybox was limited).
The following commands should work on any Unix-like system.
List by folder :
ls $(echo $PATH | tr ':' ' ')
List all commands by name
ls $(echo $PATH | tr ':' ' ') | grep -v '/' | grep . | sort
Use "which searchstr". Returns either the path of the binary or the alias setup if it's an alias
Edit:
If you're looking for a list of aliases, you can use:
alias -p | cut -d= -f1 | cut -d' ' -f2
Add that in to whichever PATH searching answer you like. Assumes you're using bash..
Try this script:
#!/bin/bash
echo $PATH | tr : '\n' |
while read e; do
for i in $e/*; do
if [[ -x "$i" && -f "$i" ]]; then
echo $i
fi
done
done
For Mac users (find doesn't have -executable and xargs doesn't have -d):
echo $PATH | tr ':' '\n' | xargs -I {} find {} -maxdepth 1 -type f -perm '++x'
Alternatively, you can get a convenient list of commands coupled with quick descriptions (as long as the command has a man page, which most do):
apropos -s 1 ''
-s 1 returns only "section 1" manpages which are entries for executable programs.
'' is a search for anything. (If you use an asterisk, on my system, bash throws in a search for all the files and folders in your current working directory.)
Then you just grep it like you want.
apropos -s 1 '' | grep xdg
yields:
xdg-desktop-icon (1) - command line tool for (un)installing icons to the desktop
xdg-desktop-menu (1) - command line tool for (un)installing desktop menu items
xdg-email (1) - command line tool for sending mail using the user's preferred e-mail composer
xdg-icon-resource (1) - command line tool for (un)installing icon resources
xdg-mime (1) - command line tool for querying information about file type handling and adding descriptions for new file types
xdg-open (1) - opens a file or URL in the user's preferred application
xdg-screensaver (1) - command line tool for controlling the screensaver
xdg-settings (1) - get various settings from the desktop environment
xdg-user-dir (1) - Find an XDG user dir
xdg-user-dirs-update (1) - Update XDG user dir configuration
The results don't appear to be sorted, so if you're looking for a long list, you can throw a | sort | into the middle, and then pipe that to a pager like less/more/most. ala:
apropos -s 1 '' | sort | grep zip | less
Which returns a sorted list of all commands that have "zip" in their name or their short description, and pumps that the "less" pager. (You could also replace "less" with $PAGER and use the default pager.)
Try to press ALT-? (alt and question mark at the same time). Give it a second or two to build the list. It should work in bash.
Here's a solution that gives you a list of all executables and aliases. It's also portable to systems without xargs -d (e.g. Mac OS X), and properly handles paths with spaces in them.
#!/bin/bash
(echo -n $PATH | tr : '\0' | xargs -0 -n 1 ls; alias | sed 's/alias \([^=]*\)=.*/\1/') | sort -u | grep "$#"
Usage: myscript.sh [grep-options] pattern, e.g. to find all commands that begin with ls, case-insensitive, do:
myscript -i ^ls
It's useful to list the commands based on the keywords associated with the command.
Use: man -k "your keyword"
feel free to combine with:| grep "another word"
for example, to find a text editor:
man -k editor | grep text
shortcut method to list out all commands.
Open terminal and press two times "tab" button.
Thats show all commands in terminal
You can always to the following:
1. Hold the $PATH environment variable value.
2. Split by ":"
3. For earch entry:
ls * $entry
4. grep your command in that output.
The shell will execute command only if they are listed in the path env var anyway.
it depends, by that I mean it depends on what shell you are using. here are the constraints I see:
must run in the same process as your shell, to catch aliases and functions and variables that would effect the commands you can find, think PATH or EDITOR although EDITOR might be out of scope. You can have unexported variables that can effect things.
it is shell specific or your going off into the kernel, /proc/pid/enviorn and friends do not have enough information
I use ZSH so here is a zsh answer, it does the following 3 things:
dumps path
dumps alias names
dumps functions that are in the env
sorts them
here it is:
feed_me() {
(alias | cut -f1 -d= ; hash -f; hash -v | cut -f 1 -d= ; typeset +f) | sort
}
If you use zsh this should do it.
The problem is that the tab-completion is searching your path, but all commands are not in your path.
To find the commands in your path using bash you could do something like :
for x in echo $PATH | cut -d":" -f1; do ls $x; done
Here's a function you can put in your bashrc file:
function command-search
{
oldIFS=${IFS}
IFS=":"
for p in ${PATH}
do
ls $p | grep $1
done
export IFS=${oldIFS}
}
Example usage:
$ command-search gnome
gnome-audio-profiles-properties*
gnome-eject#
gnome-keyring*
gnome-keyring-daemon*
gnome-mount*
gnome-open*
gnome-sound-recorder*
gnome-text-editor#
gnome-umount#
gnome-volume-control*
polkit-gnome-authorization*
vim.gnome*
$
FYI: IFS is a variable that bash uses to split strings.
Certainly there could be some better ways to do this.
maybe i'm misunderstanding but what if you press Escape until you got the Display All X possibilities ?
compgen -c > list.txt && wc list.txt
Why don't you just type:
seachstr
In the terminal.
The shell will say somehing like
seacrhstr: command not found
EDIT:
Ok, I take the downvote, because the answer is stupid, I just want to know: What's wrong with this answer!!! The asker said:
and see if a command is available.
Typing the command will tell you if it is available!.
Probably he/she meant "with out executing the command" or "to include it in a script" but I cannot read his mind ( is not that I can't regularly it is just that he's wearing a
mind reading deflector )
in debian: ls /bin/ | grep "whatImSearchingFor"

Resources