Canned Bash lessons - learn to use Bash commands

Programs intended to teach, or to help one learn or study a specific subject - this includes educational games.
Message
Author
User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#21 Post by technosaurus »

Code: Select all

#using shell builtins to replace long pipes of external commands
#
#while read A || [ "$A" ]; do A=`echo $A`;echo ${A};done <<<"${VAR}" |
#or
#while read A || [ "$A" ]; do A=`echo $A`;echo ${A};done <$FILE |
#can replace:
# echo "${VAR}" |tr "\t" " "|tr -s " "|cut/sed ... |
#or
# cat $FILE |tr "\t" " "|tr -s " "|cut/sed ... |
#
#both tr commands are replaced with VAR=`echo $VAR`
#cut is replace with the second <and third> echo using substring manipulation
#use:
# echo ${A#* * *} to remove the first 3 fields or ${A%* * *} to remove the last 3
#there is another alternative if you no longer need the input parameters
#use:
# set `echo $A`; echo $1,$5,$7 ... this uses the 1st,5th&7th " " separated word
#you can also use the IFS value if you want "|" to separate words
#ex.  OLDIFS="${IFS}";IFS="|";...commands...;IFS="${OLDIFS}"
#sed can often be replaced with thie ${VAR///} substring manipulations
#use:
# echo ${A//"${OLDSTRING}"/"${NEWSTRING}"} as a sed replacement
#NOTE this method will work for multiple lines while sed will not
#NOTE on IFS and read, set etc...
#you can get creative with read and IFS too, but it can get difficult to follow
#normally read uses a new line (represented by \n) as the delimiter
#_some_ shells have -d parameter for read, but for portability set/reset IFS
#be careful though, setting IFS will affect other commands too, for example
#set `echo "a b c d e f"`; echo $1 .... "a b c d e f" when IFS="|" ...oops
#this is a feature, not a bug
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

User avatar
smokey01
Posts: 2813
Joined: Sat 30 Dec 2006, 23:15
Location: South Australia :-(
Contact:

#22 Post by smokey01 »

Is there a more efficient way to do this?

Code: Select all

#!/bin/bash
if [[ $1 == *.png ]]
then
/usr/bin/geany 
else
if [[ $1 == *.PNG ]]
then
/usr/bin/geany 
else
if [[ $1 == *.jpeg ]]
then
/usr/bin/geany
else
if [[ $1 == *.jpg ]]
then
/usr/bin/geany
else
if [[ $1 == *.pet ]]
then
/usr/bin/viewnior
else
/usr/bin/mtpaint
fi fi fi fi fi
Is there a way to use an OR operator or something similar.

The applications are there specifically to test the code.

When this script is placed on the desktop and a file is dropped on it, an action takes place depending on the type of file that is dropped on the script file.

Something like the below would be nice:

Code: Select all

#!/bin/bash
if [[ $1 == *.png or *.jpg or *.jpeg or *.PNG ]]
then
do something
else
do something else
fi
TIA

User avatar
maxerro
Posts: 53
Joined: Sun 10 Oct 2010, 16:11

#23 Post by maxerro »

smokey01 wrote:Is there a more efficient way to do this?

Code: Select all

case $1 in
 *.png|*.PNG|*.jpg|*.jpeg) process_pic;;
 *.pet|*.deb|*.rpm) process_pkg;;
 *) do_something_else;;
esac
Don't forget ;; at the end of each case.

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#24 Post by technosaurus »

maxerro wrote:
smokey01 wrote:Is there a more efficient way to do this?

Code: Select all

case $1 in
 *.png|*.PNG|*.jpg|*.jpeg) process_pic;;
 *.pet|*.deb|*.rpm) process_pkg;;
 *) do_something_else;;
esac
Don't forget ;; at the end of each case.
if we are still using ROX-Filer...

Code: Select all

rox $@
or if we keep the mime-types directory

Code: Select all

#!/bin/sh
MIME=`file -b --mime-type $1`
/root/Choices/MIME-types/${MIME//\//_} $1
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

User avatar
smokey01
Posts: 2813
Joined: Sat 30 Dec 2006, 23:15
Location: South Australia :-(
Contact:

#25 Post by smokey01 »

Thanks guys.

maxerro your works a treat.

Techno I'm not sure how to implement yours so it will do something when a particular file is selected.

The other little problem I've noticed is if you select more than one type of file, eg: *.pet and *.zip at the same time it copies them both to the same directory.

I am using variable $1 to $9, so in theory I should be able to copy 9 files at a time.

Any ideas?

Thanks

User avatar
maxerro
Posts: 53
Joined: Sun 10 Oct 2010, 16:11

#26 Post by maxerro »

smokey01 wrote:...little problem I've noticed is if you select more than one type of file, eg: *.pet and *.zip at the same time it copies them both to the same directory...

Code: Select all

#!/bin/bash
for ((i=1; i<=$#; i++)); do
 case "${!i}" in
  *.pet|*.deb|*.rpm) busybox cp "${!i}" /destination1 &;;
  *.zip|*.rar|*.bz2) busybox cp "${!i}" /destination2 &;;
  *) busybox cp "${!i}" /destination3 &;;
 esac
done
$# is the number of arguments passed. ${!i} is the value of the i-th argument. This is one of the faster ways. If it causes problems, use classic cp, without busybox and drop & in the end. (It will be MUCH slower.) Be careful if the destination contains spaces, you may need to enclose (some part of) it in double quotes.

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#27 Post by technosaurus »

or simply

Code: Select all

#!/bin/sh
for i in "$@"; do
 case "${i}" in
  *.pet|*.deb|*.rpm) busybox cp "${i}" /destination1 &;;
  *.zip|*.rar|*.bz2) busybox cp "${i}" /destination2 &;;
  *) busybox cp "${i}" /destination3 &;;
 esac
done
BTW the reason I used file before was to catch things like png images with an xpm extension
Last edited by technosaurus on Thu 15 Dec 2011, 09:34, edited 1 time in total.
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

User avatar
maxerro
Posts: 53
Joined: Sun 10 Oct 2010, 16:11

#28 Post by maxerro »

We should also mention the 3rd (shifting) way, which preserves escape-codes in arguments, why some would say that it should be #1 choice.

Code: Select all

#!/bin/sh
while [ $# -ne 0 ]; do
 case "$1" in 
  *.pet|*.deb|*.rpm) busybox cp "$1" /dst1 &;; 
  *.zip|*.rar|*.bz2) busybox cp "$1" /dst2 &;; 
  *) busybox cp "$1" /dst3 &;; 
 esac 
 shift
done
As you see, the loop will work until it runs-out of arguments. Shift command trashes the $1 argument, so $2 becomes $1, $3>$2, and so on... That's why only $1 is used in every new iteration.

User avatar
smokey01
Posts: 2813
Joined: Sat 30 Dec 2006, 23:15
Location: South Australia :-(
Contact:

#29 Post by smokey01 »

Very informative. Thanks.

The reason I needed to know this was to create a dropbox type application so I could use it with my own web server.

By just placing the script on the desktop or in OpenWith, I can upload software to my server. The script now allows me to mix file types but they are now copied to the appropriate directory on the server.

Using quotes around the variable allows copying of filenames with spaces, another good feature.

I am using a command line FTP utility to send the files to my web server.

All in all this has become a very useful application.

If you like I can post the FTP client I compiled with the final script or even PET it up.

Thanks so much for your help.

Post Reply