[bash] Script to grab a screen area (copy/paste)

Share your own howto's etc. Not for support questions!

[bash] Script to grab a screen area (copy/paste)

Postby test666v2 » 2014-06-09 20:37

This resulted from a very specific need: grab several images with very different sizes and pasting them to other programs.

I searched but found no way of doing this any other way other than saving the entire screen to file, opening the file (with gimp or any other image editor), croping, copying and finally pasting the desired section. Probably my google foo is very weak.

This script is very crude, but it worked.

There are four dependencies for this script to work:
- eog
- scrot
- esd_cat (from xosd-bin)
- xmessage (already installed)

install with:
sudo apt-get install eog scrot xosd-bin

The script will test if these 3 dependencies are installed.

Copy/paste the script to a text editor, save it to your scripts folder, make it executable with:
chmod +x [path_to_scripts_folder]/screenshot_select_copy_to_clipboard.sh

I tried to comment the script as much as I could, so it will not be a black box for the common user. Please read the supplied explanations and implement your tweaking as needed.

Code: Select all
#!/bin/bash

########################
#by test666v2, june 2014
#modify if/as needed
#BSD license, modified

#Copyright (c) 2014, test666v2
# All rights reserved.
########################

#Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
#Redistributions of source code must retain the above copyright notice, this list of conditions, the General Notes, The Disclaimer, the Political note, the Description and Personal notes, and the following disclaimer.
#Redistributions in any form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
#Neither the name of the <reddit> nor the names of its contributors may be used to endorse or promote products derived from this software.

#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

########################

# Disclaimer
# 1 - there are rough edges, I'm forever a learning newbie...
# 2 - use this script at your own risk, because it may kill your machine
# 3 - no assistance, I just don't have the time
# 4 - don't contact me except in the this thread and even so I may never answer (see #3)
# 5 - #3 & #4 : sorry, not playing role as a snob, I am honestly deprived of time
# 6 - good luck

########################

# Political note
# 1 - ubuntu unity sucks, lubuntu is ok, Debian LXDE (where I am now) is way cool
# 2 - #1 NOT flame bait, just venting, cool it, keep it to yourself, no issue here, move along

########################

# Description and Personal notes

# simple script to select a screen region and copy that to other programs

#my keyboard shortcut for "quickly" selecting a screen region and pasting to other programs is
# < control > < alt > < p >

#in Debian LXDE:
#leafpad /home/user/.config/openbox/lxde-rc.xml
#and insert
#<keybind key="C-A-p"><action name="Execute"><command>/home/user/scripts/screenshot_select_copy_to_clipboard.sh</command></action></keybind>

# tested with debian jessie, ubuntus are probably ok, adapt if/as needed for other distros

# must be installed (dependencies):
# - eog - "Eye of GNOME graphics viewer program" : will be TESTED
# - scrot - "command line screen capture utility" : will be TESTED
# - xosd-bin (for esd_cat) - "X On-Screen Display library - binary files" : will be TESTED
# - xmessage - X11 utilities -- almost always installed - watchout fedorians & others, it may not be installed : will NOT TEST for this missing dependency

# congratulations, you guessed it, english is not my native language :-))

# finally, after this inflamated and gargantuan/highly_bloated considerations, let's see what this script does

########################

# function 1
#test if the dependencies are installed (but not for xmessage, which is assumed installed)

test_dependencies()
{
   dependency_descriptor[1]="Eye of GNOME graphics viewer program"
   dependency_prog[1]=eog
   dependency_descriptor[2]="command line screen capture utility"
   dependency_prog[2]=scrot
   dependency_descriptor[3]="X On-Screen Display library - binary files"
   dependency_prog[3]=xosd-bin
#get list of installed packages
   store="$(dpkg --list)"
#check for missing dependencies (1 to 3); sorry, hairy stuff next; ;-) there are other much simpler ways to do this, even without looping; it was ok for testing my poor bash skills
for (( i = 1; i <= 3; i++ ))
   do
      [[ (($(echo "$store" | grep ${dependency_prog[$i]} | grep -c "${dependency_descriptor[$i]}") == 1)) ]] || error+="\n****\n"${dependency_descriptor[$i]}" not installed\nsudo apt-get install "${dependency_prog[$i]}"\n****\n"
   done
# if string $error is not empty, there are dependencies missing; display message reporting the missing dependencies
   if ! [ -z $error ]; then
      printf "$error" | xmessage -geometry 800x300 -title "screenshot_select_copy_to_clipboard.sh  ERROR" -file - -center -buttons "  ok  "
      exit
   fi
}

#########################

# function 2
#launch needed program and display at the top center a message with short instructions

launch_and_wait_to_terminate ()
{
#get the name of the program to launch
   prog=$(echo "$1" | awk '{print $1}')
# kill the $prog if it was left stalled in some previous run
   [ $(ps aux | grep -v grep | grep -c $prog ) == 0 ] || killall -9 $prog
#execute the first program and instructions
   eval "$1" &
#while loop: wait for $prog to be accounted by ps; probably only necessary for ultra slow processors
   while (($(ps aux | grep -v grep | grep -c $prog ) == 0))
      do
         sleep 0.05
      done
# display message in the top at the center until $prog terminates (sorry, this is where I prefer to have messages, adapt as needed)
   while (($(ps aux | grep -v grep | grep -c $prog ) != 0))
      do
         echo "$2" | osd_cat -w -d 1 -c yellow -p top -A centre -l 1 -f '-b&h-lucida-bold-r-normal-sans-14-140-75-75-p-92-iso8859-1' &
         sleep 0.2
      done   
}

########################

# main

#test for dependencies
test_dependencies

#transitory (randomized) filename to save the to be selected image area
filename="/tmp/clipboard_image_"$(< /dev/urandom tr -dc 0-9,A-Z,a-z | head -c${1:-10};echo)".png"

#remove possible previous trash
! [ -f /tmp/clipboard_image_*.png ] || rm /tmp/clipboard_image_*.png

#grab a screen area; display at the top center a message with short instructions for copying screen area
launch_and_wait_to_terminate "scrot -s -q 100 $filename" "mouse : select region  |||  mouse actions : click, hold, drag, release"

#launch image viewer; display at the top center a message with short instructions for copy/paste
launch_and_wait_to_terminate "eog $filename" "<control> <c> to copy   |   <control> <v> to paste"

#remove the transitory image file
rm "$filename"

exit


I am really deprived of time, but will gladly accept sugestions and corrections. Thank you for your time.
test666v2
 
Posts: 2
Joined: 2014-06-09 20:02

Re: [bash] Script to grab a screen area (copy/paste)

Postby test666v2 » 2014-06-22 12:03

Updated.

Reasons:

1 - minor tweaking in the script messages

2 - removed & and sleep (dumb scripting) from function 2, lines 109 and 110

2 - added a "function 3", to solve the issue (visual pollution by overwriting top message area) when more than one script were left stalled
2.1 - buggy: the script will kill the opened version of itself when opened for editing; dumb, but no time now to solve this

3 - some caveats: upon starting, the script will kill every instance of:
3.1 - eog
3.2 - scrot

Point 3 will probably disappear so to only kill instances of eog and scrot that were launched by this script. No time to investigate how to do this for now. Probably autosolved because by going through function 3, killing zombies of itself will only kill the instances of eog and scrot launched by previous scripts (whishful thinking?).

********************

FAQ

1 - Why use scrot/eog?
Because they seemed to be the fastest in their field of expertise

2 - Can you (add suggestion/reasoning here)?
Sorry, I may not, this was fun to do and it resulted from a very specific need in a very specific time in my life, but I do lack the knowhow and the motivation to work in your suggestion/reasoning and the time to do what you may want/wish (not bitching, no flame bait, just a simple fact of my life)

3 - Can I modify your script?
Short answer: Please do so.
Long answer: Of course, that was my main motivation to put it online. Improve it or simply discard it completely. Remember, your motivations => your code. Also remember, if you do take some, give some.

[code]
#!/bin/bash

########################
#by test666v2, june 2014
#modify if/as needed
#BSD license, modified

#Copyright (c) 2014, test666v2
# All rights reserved.
########################

#Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
#Redistributions of source code must retain the above copyright notice, this list of conditions, the General Notes, The Disclaimer, the Political note, the Description and Personal notes, and the following disclaimer.
#Redistributions in any form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
#Neither the name of the <reddit> nor the names of its contributors may be used to endorse or promote products derived from this software.

#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

########################

# Disclaimer
# 1 - there are rough edges, I'm forever a learning newbie...
# 2 - use this script at your own risk, because it may kill your machine
# 3 - no assistance, I just don't have the time
# 4 - don't contact me except in the reddit thread and even so I may never answer (see #3)
# 5 - #3 & #4 : sorry, not playing role as a snob, I am honestly deprived of time
# 6 - good luck

########################

# Political note
# 1 - ubuntu unity sucks, lubuntu is ok, Debian LXDE (where I am now) is way cool
# 2 - #1 NOT flame bait, just venting, cool it, keep it to yourself, no issue here, move along

########################

# Description and Personal notes

# simple script to select a screen region and copy that to other programs

#my keyboard shortcut for "quickly" selecting a screen region and pasting to other programs is
# < control > < alt > < p >

#in Debian LXDE:
#leafpad /home/user/.config/openbox/lxde-rc.xml
#and insert
#<keybind key="C-A-p"><action name="Execute"><command>/home/user/scripts/screenshot_select_copy_to_clipboard.sh</command></action></keybind>

# tested with debian jessie, ubuntus are probably ok, adapt if/as needed for other distros

# must be installed (dependencies):
# - eog - "Eye of GNOME graphics viewer program" : will be TESTED
# - scrot - "command line screen capture utility" : will be TESTED
# - xosd-bin (for esd_cat) - "X On-Screen Display library - binary files" : will be TESTED
# - xmessage - X11 utilities -- almost always installed - watchout fedorians & others, it may not be installed : will NOT TEST for this missing dependency

# congratulations, you guessed it, english is not my native language :-))

# finally, after this inflamated and gargantuan/highly_bloated considerations, let's see what this script does

########################

# function 1
#test if the dependencies are installed (but not for xmessage, which is assumed installed)

test_dependencies()
{
dependency_descriptor[1]="Eye of GNOME graphics viewer program"
dependency_prog[1]=eog
dependency_descriptor[2]="command line screen capture utility"
dependency_prog[2]=scrot
dependency_descriptor[3]="X On-Screen Display library - binary files"
dependency_prog[3]=xosd-bin
#get list of installed packages
store="$(dpkg --list)"
#check for missing dependencies (1 to 3); sorry, hairy stuff next; ;-) there are other much simpler ways to do this, even without looping; it was ok for testing my poor bash skills
for (( i = 1; i <= 3; i++ ))
do
[[ (($(echo "$store" | grep ${dependency_prog[$i]} | grep -c "${dependency_descriptor[$i]}") == 1)) ]] || error+="\n****\n"${dependency_descriptor[$i]}" not installed\nsudo apt-get install "${dependency_prog[$i]}"\n****\n"
done
# if string $error is not empty, there are dependencies missing; display message reporting the missing dependencies
if ! [ -z $error ]; then
printf "$error" | xmessage -geometry 800x300 -title "screenshot_select_copy_to_clipboard.sh ERROR" -file - -center -buttons " ok "
exit
fi
}

#########################

# function 2
#launch needed program and display at the top center a message with short instructions

launch_and_wait_to_terminate ()
{
#get the name of the program to launch
prog=$(echo "$1" | awk '{print $1}')
# kill the $prog if it was left stalled in some previous run
[ $(ps aux | grep -v grep | grep -c $prog ) == 0 ] || killall -9 $prog
#execute the first program and instructions
eval "$1" &
#while loop: wait for $prog to be accounted by ps; probably only necessary for ultra slow processors
while (($(ps aux | grep -v grep | grep -c $prog ) == 0))
do
sleep 0.05
done
# display message in the top at the center until $prog terminates (sorry, this is where I prefer to have messages, adapt as needed)
while (($(ps aux | grep -v grep | grep -c $prog ) != 0))
do
# echo "$2" | osd_cat -w -d 0.5 -c yellow -p top -A centre -l 1 -f '-b&h-lucida-bold-r-normal-sans-14-140-75-75-p-92-iso8859-1' &
echo "$2" | osd_cat -w -d 1 -c yellow -p top -A centre -l 1 -f '-b&h-lucida-bold-r-normal-sans-14-140-75-75-p-92-iso8859-1'
# sleep 0.2
done
}


#########################

# function 3
# check to see if there are more instances of this script running and kill them

zombies_be_gone()
{
#what is this script name and path?
me=$(readlink -f $0)
#test for a full path to the script
if [ "$me" != "$0" ]; then
echo "Error detected"
echo "This script must be run with a full path, as in:"
echo "/home/username/my_scripts/screenshot_select_copy_to_clipboard.sh"
echo
exit
fi
#how many zombies of me were left hanging?
#a count of 2 means the grep call is also accounted; so 2 is OK
how_many_zombies=$(ps aux | grep -v grep | grep -c $me)
#if there are more scripts like me running (my zombies), let's clean up the mess
if [ $how_many_zombies -gt 2 ]; then
#what is this script PID?
my_pid=$(echo $$)
#what are my zombies hanging PIDs?
#getting this twice allows us to find and later exclude via SORT+UNIQ the PID issued to grep
for (( i = 1; i <= 2; i++ ))
do
#get PIDs, but exclude this script own PID
pids_list+=$(ps aux | grep $me | grep -v $my_pid | grep -v grep | awk '{print $2}')' '
done
# interject a newline (substituting spaces) between PIDS so SORT+UNIQ can do their magic
pids_to_kill=$(echo -e $pids_list | sed -e "s/\s\s*/\\\n/g")
#eliminate duplicate pid numbers (SORT+UNIQ magic trick)
pids_to_kill=$(echo -e $pids_to_kill | sort -n | uniq -d | { s=$(< /dev/stdin); echo $s; };)
#let's kill those dormant zombies by their PIDs
for every_pid in $pids_to_kill
do
kill -9 $every_pid
done
fi
}

########################

# main

#test for dependencies
test_dependencies

#search for and kill zombies
zombies_be_gone

#transitory (randomized) filename to save the to be selected image area
filename="/tmp/clipboard_image_"$(< /dev/urandom tr -dc 0-9,A-Z,a-z | head -c${1:-10};echo)".png"

#remove possible previous trash
! [ -f /tmp/clipboard_image_*.png ] || rm /tmp/clipboard_image_*.png

#grab a screen area; display at the top center a message with short instructions for copying screen area
launch_and_wait_to_terminate "scrot -s -q 100 $filename" "mouse : select region and execute mouse actions : click, hold, drag, release"

#launch image viewer; display at the top center a message with short instructions for copy/paste
launch_and_wait_to_terminate "eog $filename" "<control> <c> to copy and <control> <v> to paste"

#remove the transitory image file
rm "$filename"

exit

[code]
test666v2
 
Posts: 2
Joined: 2014-06-09 20:02


Return to Docs, Howtos, Tips & Tricks

Who is online

Users browsing this forum: No registered users and 4 guests

fashionable