I am doing a project which behaves like autologin using xdotool. Below is the bash script command:
if [ "$url" == "https://github.com/login" ]; then
sleep 5
xdotool type $WUSER
xdotool key Tab
xdotool type $DECPASS
xdotool key Return
else
exit 1
fi
There will be a default URL for login page (eg: https://github.com/login), which will run this script below on the browser startup:
automatically type in the username
press tab key
type in the password
click enter
At the moment I use sleep 5 (wait 5 seconds until running the next command) which is a bit hacky because some pages load really fast and others don't.
Question
How to check first if the page is fully loaded before running the command? Maybe it will look something like this, or if there's some other better methods.
if [ "$url" == "https://github.com/login" ]; then
if [ <page is fully loaded> ]; then
xdotool type $WUSER
xdotool key Tab
xdotool type $DECPASS
xdotool key Return
else
<wait until page loads>
fi
else
exit 1
fi
This script's logic tries to find if login was successful, instead of trying other things first. This makes it easy for in bash, because other solutions (in bash) are complicated or undoable.
While all these may be great, they can make it very complicated for you.
Instead you want to make it simple for you.. then try this:
sleep 5;
if [[ <check with xdotool search --name for a window to confirm login> ]];
echo " Window exists, login was successful;
else
echo "Login failed, retring.
<Repeat login>
fi;
For instance, I know when I (sucessfully )login to Github, there is a page titled "Github".
Before login, there is a page "Sign in to Github"
So may be i can check if sign in to github page still exists.
#so you'r script will look like this
#keep trying to login, til successs
while true;
do
sleep 5;
#your code to Log-in
if [[ -z "$(xdotool search --name "Sign in to GitHub")" ]];
then
echo "I reckon login was succesfful.";
break 1;
else
echo "Try again.";
fi;
done;
For the above to work, the Browser window must be open in a separate window or
the Tab should be the visible one.
I have to work within three main directories under the root filesystem - home/username, project, and scratch. I want my shell prompt to display which of these top level directories i am in.
Here is what I am trying to do:
top_level_dir ()
{
if [[ "${PWD}" == *home* ]]
then
echo "home";
elif [[ "${PWD}" == *scratch* ]]
then
echo "scratch";
elif [[ "${PWD}" == *project* ]]
then
echo "project";
fi
}
Then, I export PS1 as:
export PS1='$(top_level_dir) : '
Unfortunately this is not working as I want. I get home : for my prompt when I am in my home directory, but if I switch to scratch or projects then the prompt does not change. I do not understand bash scripting very well so I would appreciate any help to correct my code.
You can hook into cd to change the prompt every time you are changing the working directory. I've asked myself often how to hook into cd but I think that I now found a solution. What about adding this to your ~/.bashrc?:
#
# Wrapper function that is called if cd is invoked
# by the current shell
#
function cd {
# call builtin cd. change to the new directory
builtin cd $#
# call a hook function that can use the new working directory
# to decide what to do
color_prompt
}
#
# Changes the color of the prompt depending
# on the current working directory
#
function color_prompt {
pwd=$(pwd)
if [[ "$pwd/" =~ ^/home/ ]] ; then
PS1='\[\033[01;32m\]\u#\h:\w\[\033[00m\]\$ '
elif [[ "$pwd/" =~ ^/etc/ ]] ; then
PS1='\[\033[01;34m\]\u#\h:\w\[\033[00m\]\$ '
elif [[ "$pwd/" =~ ^/tmp/ ]] ; then
PS1='\[\033[01;33m\]\u#\h:\w\[\033[00m\]\$ '
else
PS1='\u#\h:\w\\$ '
fi
export PS1
}
# checking directory and setting prompt on shell startup
color_prompt
Please try this method instead and tell us how it works e.g. how your prompt changes in your home directory, your project or scratch directory, and other directories besides those. Tell us what error messages you see as well. The problem lies within it.
Tell me also how you run it, if it's by script, by direct execution, or through a startup script like ~/.bashrc.
top_level_dir ()
{
__DIR=$PWD
case "$__DIR" in
*home*)
echo home
;;
*scratch*)
echo scratch
;;
*project*)
echo project
;;
*)
echo "$__DIR"
;;
esac
}
export PS1='$(top_level_dir) : '
export -f top_level_dir
If it doesn't work, try changing __DIR=$PWD to __DIR=$(pwd) and tell us if it helps too. I also would like to confirm if you're really running bash. Note that there are many variants of sh like bash, zsh, ksh, and dash and the one installed and used by default depends on every system. To confirm that you're using Bash, do echo "$BASH_VERSION" and see if it shows a message.
You should also make sure that you're running export PS1='$(top_level_dir) : ' with single quotes and not with double quotes: export PS1="$(top_level_dir) : ".
There are many questions asking about accessing the Sublime Text 2 editor from the command line. The responses, in summary, are to make a symlink, alias or simple shell script to run the appropriate sublime_text command. I can do that. What I want is to make the linux version behave like the MacOS version.
On MacOS, I have the following:
ln -s /Applications/Sublime\ Text\ 2.app/Contents/SharedSupport/bin/subl ~/bin/subl
Then in my .zshrc:
alias subl="$HOME/bin/subl -n"
export EDITOR="$HOME/bin/subl -n -w"
This does two things. It gives me a subl command that opens any files given on the command line in a new window. The subl command does not block the terminal. It also sets up my editor to open sublime text to edit the arguments, but this time it does block. In particular, $EDITOR blocks until its arguments are closed. It does not block on unrelated sublime text windows.
I can achieve a similar effect on linux with the following:
In ~/bin/subl:
#! /bin/zsh
$HOME/Sublime\ Text\ 2/sublime_text -n $# &
and then in ~/bin/subl_wait: (think mate_wait for TextMate users)
#! /bin/zsh
exec $HOME/Sublime\ Text\ 2/sublime_text -n -w $#
I can then set EDITOR to subl_wait, and things almost work. subl opens files for editing and doesn't block. subl_wait opens files for editing and does block.
The problem is that subl_wait is waiting until all open files are closed, not just its arguments.
Is it possible to get this working perfectly?
Looks like I've found the issue. (Thanks to this post: http://www.sublimetext.com/forum/viewtopic.php?f=2&t=7003 )
Basic point: sublime behaves differently depending upon whether an instance is already running!
If an instance is already running then sublime on linux behaves similarly to MacOS. If no instance is running then the terminal blocks until you exit sublime.
With that in mind, we just need to modify the scripts to make sure sublime is running:
in ~/bin/subl_start:
#! /bin/zsh
if [ ! "$(pidof sublime_text)" ] ; then
# start sublime text main instance
# echo "Starting Sublime Text 2"
$HOME/Sublime\ Text\ 2/sublime_text &
sleep 1 # needed to avoid a race condition
fi
in ~/bin/subl:
#! /bin/zsh
. $HOME/bin/subl_start
exec $HOME/Sublime\ Text\ 2/sublime_text -n $#
in ~/bin/subl_wait:
#! /bin/zsh
. $HOME/bin/subl_start
exec $HOME/Sublime\ Text\ 2/sublime_text -n -w $#
Note that I've used the -n flags everywhere. This might not be your cup of tea. If you are using -n then you possibly also want to look at your close_windows_when_empty setting.
Inspired by the OP's answer, I've created a bash wrapper script for Sublime Text that incorporates all your findings and runs on both OSX and Linux.
Its purpose is threefold:
provide a unified subl CLI that works like ST's own subl on OSX: invoke ST without blocking, unless waiting is explicitly requested.
encapsulate a workaround for the waiting-related bug on Linux.
when saved or symlinked to as sublwait, provide a sublwait CLI that automatically applies the --wait and --new-window options so as to make it suitable for use with $EDITOR (note that some programs, e.g. npm, require the $EDITOR to contain the name of an executable only - executables + options are not supported); also makes sure that at least one file is specified.
The only open question is whether the OP's approach to avoiding the race condition - sleep 1 - is robust enough.
Update:
Note that subl on OSX is by default NOT placed in the $PATH - you normally have to do that manually. If you haven't done so, the script will now locate subl inside ST's application bundle; (it tries app names in the following sequence: 'Sublime Text', 'Sublime Text 2', 'Sublime Text 3', first in /Applications, then in ~/Applications.)
Here's the output from running the script with -h:
Multi-platform (OSX, Linux) wrapper script for invocation of Sublime Text (ST)
from the command line.
Linux:
Works around undesired blocking of the shell (unless requested)
and a bug when waiting for specific files to be edited.
Both platforms:
When invoked as `sublwait`, automatically applies the
--wait --new-window
options to make it suitable for use with $EDITOR.
Therefore, you can to the following:
- Name this script `subl` for a CLI that supports ALL options.
(On OSX, this will simply defer to the `subl` CLI that came with ST.)
- Place the script in a directory in your $PATH.
- In the same directory, create a symlink to the `subl` script named
`sublwait`:
ln -s subl sublwait
and, if desired, add
export EDITOR=sublwait
to your shell profile.
Note that if you only use OSX, you can make do with ST's own subl and just save this script directly as sublwait.
Script source:
#!/usr/bin/env bash
# Multi-platform (OSX, Linux) wrapper script for invocation of Sublime Text (ST)
# from the command line. Invoke with -h for details.
[[ $1 == '-h' || $1 == '--help' ]] && showHelpOnly=1 || showHelpOnly=0
[[ $(basename "$BASH_SOURCE") == 'sublwait' ]] && invokedAsSublWait=1 || invokedAsSublWait=0
[[ $(uname) == 'Darwin' ]] && isOsX=1 || isOsX=0
# Find the platform-appropriate ST executable.
if (( isOsX )); then # OSX: ST comes with a bona-fide CLI, `subl`.
# First, try to find the `subl` CLI in the $PATH.
# Note: This CLI is NOT there by default; it must be created by symlinking it from
# its location inside the ST app bundle.
# Find the `subl` executable, ignoring this script, if named subl' as well, or a
# script by that name in the same folder as this one (when invoked via symlink 'sublwait').
stExe=$(which -a subl | fgrep -v -x "$(dirname "$BASH_SOURCE")/subl" | head -1)
# If not already in the path, look for it inside the application bundle. Try several locations and versions.
if [[ -z $stExe ]]; then
for p in {,$HOME}"/Applications/Sublime Text"{,' 2',' 3'}".app/Contents/SharedSupport/bin/subl"; do
[[ -f $p ]] && { stExe=$p; break; }
done
fi
[[ -x $stExe ]] || { echo "ERROR: Sublime Text CLI 'subl' not found." 1>&2; exit 1; }
else # Linux: `sublime_text` is the only executable - the app itself.
stExe='sublime_text'
which "$stExe" >/dev/null || { echo "ERROR: Sublime Text executable '$stExe' not found." 1>&2; exit 1; }
fi
# Show command-line help, if requested.
# Add preamble before printing ST's own help.
# Note that we needn't worry about blocking the
# shell in this case - ST just outputs synchronously
# to stdout, then exits.
if (( showHelpOnly )); then
bugDescr=$(
cat <<EOF
works around a bug on Linux (as of v2.0.2), where Sublime Text,
if it is not already running, mistakenly blocks until it is exited altogether.
EOF
)
if (( invokedAsSublWait )); then
# We provide variant-specific help here.
cat <<EOF
Wrapper script for Sublime Text suitable for use with the \$EDITOR variable.
Opens the specified files for editing in a new window and blocks the
invoking program (shell) until they are closed.
In other words: the --wait and --new-window options are automatically
applied.
Aside from encapsulating this functionality without the need for options
- helpful for tools that require \$EDITOR to be an executable name only -
$bugDescr
Usage: sublwait file ...
EOF
# Note: Adding other options doesn't make sense in this scenario
# (as of v2.0.2), so we do NOT show ST's own help here.
else
cat <<EOF
Multi-platform (OSX, Linux) wrapper script for invocation of
Sublime Text (ST) from the command line.
Linux:
Works around undesired blocking of the shell (unless requested)
and a bug when waiting for specific files to be edited.
Both platforms:
When invoked as \`sublwait\`, automatically applies the
--wait --new-window
options to make it suitable for use with \$EDITOR.
Therefore, you can to the following:
- Name this script \`subl\` for a CLI that supports ALL options.
(On OSX, this will simply defer to the \`subl\` CLI that came with ST.)
- Place the script in a directory in your \$PATH.
- In the same directory, create a symlink to the \`subl\` script named
\`sublwait\`:
ln -s subl sublwait
and, if desired, add
export EDITOR=sublwait
to your shell profile.
Sublime Text's own help:
------------------------
EOF
# Finally, print ST's own help and exit.
exec "$stExe" "$#"
fi
exit 0
fi
# Invoked as `sublwait`? -> automatically apply --wait --new-window options.
if (( invokedAsSublWait )); then
# Validate parameters.
# - We expect NO options - to keep things simple and predictable, we do NOT allow
# specifying additional options (beyond the implied ones).
# - We need at least 1 file argument.
# - As a courtesy, we ensure that no *directories* are among the arguments - ST doesn't support
# that properly (always waits for ST exit altogether); beyond that, however, we leave input
# validation to ST.
if [[ "$1" =~ ^-[[:alnum:]]+$ || "$1" =~ ^--[[:alnum:]]+[[:alnum:]-]+$ ]]; then # options specified?
{ echo "ERROR: Unexpected option specified: '$1'. Use -h for help." 1>&2; exit 1; }
elif (( $# == 0 )); then # no file arguments?
{ echo "ERROR: Missing file argument. Use -h for help." 1>&2; exit 1; }
else # any directories among the arguments?
# Note: We do NOT check for file existence - files could be created on demand.
# (Things can still go wrong - e.g., /nosuchdir/mynewfile - and ST doesn't
# handle that gracefully, but we don't want to do too much here.)
for f in "$#"; do
[[ ! -d "$f" ]] || { echo "ERROR: Specifying directories is not supported: '$f'. Use -h for help." 1>&2; exit 1; }
done
fi
# Prepend the implied options.
set -- '--wait' '--new-window' "$#"
fi
# Finally, invoke ST:
if (( isOsX )); then # OSX
# `subl` on OSX handles all cases correctly; simply pass parameters through.
exec "$stExe" "$#"
else # LINUX: `sublime_text`, the app executable itself, does have a CLI, but it blocks the shell.
# Determine if the wait option was specified.
mustWait=0
if (( invokedAsSublWait )); then
mustWait=1
else
# Look for the wait option in the parameters to pass through.
for p in "$#"; do
[[ $p != -* ]] && break # past options
[[ $p == '--wait' || $p =~ ^-[[:alnum:]]*w[[:alnum:]]*$ ]] && { mustWait=1; break; }
done
fi
if (( mustWait )); then # Invoke in wait-for-specified-files-to-close mode.
# Quirk on Linux:
# If sublime_text isn't running yet, we must start it explicitly first.
# Otherwise, --wait will wait for ST *as a whole* to be closed before returning,
# which is undesired.
# Thanks, http://stackoverflow.com/questions/14598261/making-sublime-text-2-command-on-linux-behave-as-it-does-on-macos-x
if ! pidof "$stExe" 1>/dev/null; then
# Launch as BACKGROUND task to avoid blocking.
# (Sadly, the `--background` option - designed not to activate the Sublime Text window
# on launching - doesn't actually work on Linux (as of ST v2.0.2 on Ubuntu 12.04).)
("$stExe" --background &)
# !! We MUST give ST some time to start up, otherwise the 2nd invocation below will be ignored.
# ?? Does a fixed sleep time of 1 second work reliably?
sleep 1
fi
# Invoke in blocking manner, as requested.
exec "$stExe" "$#"
else # Ensure invocation in NON-blocking manner.
if ! pidof "$stExe" 1>/dev/null; then # ST isn't running.
# If ST isn't running, invoking it *always* blocks.
# Therefore, we launch it as a background taks.
# Invocation via a subshell (parentheses) suppresses display of the
# background-task 'housekeeping' info.
("$stExe" "$#" &)
else # ST is already running, we can safely invoke it directly without fear of blocking.
exec "$stExe" "$#"
fi
fi
fi
On Ubuntu Gnu/Linux 13.04 64-bit:
I just keep subl running pretty much all the time. So my git config has:
core.editor=/usr/bin/subl -n -w
And that's all I need. I save the git commit file with ctrl-s, close the window with ctrl-w and I'm done. But I then have to really close the window by hitting the X in the upper corner... 96% perfect.
I'm trying to write a script to launch xfce and xbmc in their own x sessions.
To do this I'm setting the DISPLAY value, running the first one in the background and waiting until I get a successful return from xset q. Then I change DISPLAY and do the same for the other.
I'm writing this piece by piece to check I've got the syntax right for each part and the part I'm stuck on is the 'waiting until I get a successful return from xset q.
export DISPLAY=":0.0"
while [[ ! `xset q` ]]
do
echo -n "."
done
This code seems to work so when XFCE is running it exits immediately and when it is not it sits there printing .xset: unable to open display ":0.0"
However I don't want to see the output of xset so I'm trying to redirect its output.
export DISPLAY=":0.0"
while [[ ! `xset q > /dev/null 2>&1` ]]
do
echo -n "."
done
Adding this redirection however seems to break the detection, and regardless of whether XFCE is running or not it just sits there printing dots.
I've tested the two commands on their own and in a shell script on their own they both work as I expect, returning 1 when XFCE is not running and 0 when it is.
Can anyone explain why putting that command inside of [[ ! `…` ]] breaks the while test and how I could rewrite this while loop correctly?
(Running on Arch)
The problem is that you're not testing the return code of xset at all, you processing it's output. When you redirect the output to /dev/null, the expression in backticks doesn't return anything, it's as if you had:
while [[ ! '' ]] ...
which will always run the while body.
What you should be doing is:
while ! xset q > /dev/null 2>&1
do
...
done
HI,
I have cygwin installed in my Windows system.
I have written two function in my profile file so that every time I open vi/vim, it will open with gvim.
But with this one of the issue, the windows path and Cygwin path. I tried with Cygpath as below:
function vi ()
{
win_file_path=$(cygpath -w $*)
gvim "$win_file_path" &
}
Bu with this, when ever I open a file like this: "vi /etc/exports +5", it will result in error. So let me know if any of you have any solution.
You can treat the file arguments only:
function vi ()
{
local -a viargs
local a
while [[ $# -gt 0 ]]
do
a="$1"
if [ -e "$a" ]; then a="$(cygpath -w "$a")"; fi
viargs[${#viargs[#]}]="$a"
shift
done
gvim "${viargs[#]}" &
}
Instead of being 'smart' about existing files like this, feel free to simplify to treat just the first argument :)
In recent bash versions you can replace the ugly line
viargs[${#viargs[#]}]="$a"
with
viargs+=( "$a" )
cyg-wrapper has been written for this sole purpose.
NB: See also the related wikia page.