LinuxQuestions.org
Support LQ: Use code LQ3 and save $3 on Domain Registration
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 11-03-2010, 02:23 PM   #1
onsem
LQ Newbie
 
Registered: Nov 2010
Posts: 6

Rep: Reputation: 0
Bash script


Hi I've got stuck in bash script. I'm writing a script which searches scripts in entered directory and its subdirectories. Scripts are searched on the basis of the first line e.g.: #!/bin/bash or perl,awk,...
My script should display file name,path and script name.

e.g.: if I enter directory "script" it will display

/home/my/script/aaa.sh bash
/home/my/script/first/bbb.pl perl
/home/my/script/second/ccc.sh bash

I've tried this, but no success:

find $directory_name -exec grep -H -l "bash" '{}' \;

- this searches in whole file not just in first line. I was thinking about this "| head -n 1" but don't know how to implement it
- in addition to this I need to display script name

Thanks for help
 
Old 11-03-2010, 03:59 PM   #2
martinbc
Member
 
Registered: Jun 2010
Distribution: Ubuntu, played with Puppy Slitaz & OpenSUSE
Posts: 40

Rep: Reputation: 4
Hi

I'm not good with find but does this command work ok?
Code:
grep -R -n '^#!/bin' * | grep ":1:" | sed s/......bin./\ /
-R recursively searches
-n sticks the matching line number into the output of the first grep
Piping into a second grep can check that only the first line is considered
Piping that into sed strips out the line number and #!/bin/

Martin
 
1 members found this post helpful.
Old 11-03-2010, 05:47 PM   #3
macemoneta
Senior Member
 
Registered: Jan 2005
Location: Manalapan, NJ
Distribution: Fedora x86 and x86_64, Debian PPC and ARM, Android
Posts: 4,593
Blog Entries: 2

Rep: Reputation: 332Reputation: 332Reputation: 332Reputation: 332
Or you could just:

Code:
find $directory_name -type f -executable -exec file {} \; | grep script
 
Old 11-03-2010, 05:47 PM   #4
serafean
Member
 
Registered: Mar 2006
Location: Czech Republic
Distribution: Gentoo, Chakra
Posts: 903
Blog Entries: 13

Rep: Reputation: 122Reputation: 122
Hi,
may I suggest, that before fiddling around with find, you use the bash "for" loop? (it'll simplify things a bit for you for now, at least it did for me)
to get the first line of file :
Code:
sed -n 1p $file | grep -o "bash"
This is a quick dump of what came first to mind, it doesn't ouptut in the format you wish, but thats a bit of fiddling I'll leave up to you

If you need help, come back

Serafean

Last edited by serafean; 11-03-2010 at 06:04 PM. Reason: stupid solution
 
Old 11-03-2010, 06:13 PM   #5
onsem
LQ Newbie
 
Registered: Nov 2010
Posts: 6

Original Poster
Rep: Reputation: 0
Thanks for reply. This works quite good but it returns everything not just bash/perl/... scripts.

Code:
grep -R -n '^#!/bin' * | grep ":1:" | sed s/......bin./\ /
It would be better if that script finds the script files and then just print path and name of the scrip.


Can you post some example with the for cycle. Maybe little adapted to the form of output I require?
When this script first came to my mind I tried this:

Code:
for i in $(directory_name); do grep -H -l -s "bash" | head -n 1; done
but it didn't work.

Thanks

Last edited by onsem; 11-04-2010 at 04:25 AM.
 
Old 11-04-2010, 12:07 PM   #6
serafean
Member
 
Registered: Mar 2006
Location: Czech Republic
Distribution: Gentoo, Chakra
Posts: 903
Blog Entries: 13

Rep: Reputation: 122Reputation: 122
Hi, this outputs exactly what you want
Code:
grep -H -o "\#\!/bin/bash" * | sed  's/\#\!\/bin\///'
but has the downside, that it doesn't check the line number #!/bin/bash was found on. IMO you'll need an if statement in there somewhere, whatever you do.

with the for cycle, it gives about this :
Code:
for i in *; do
if [ -f $i ];then
        type=`sed -n 1p $i | grep -o "bash"`
        if [ ! -z $type ];then
                echo -n "$i "
                echo "$type"
        fi
fi
done
This works for one directory, to make it go deeper, another if statement that makes the function call itself is necessary. However, I think that now that it works for one directory, sticking with the find command is cleaner. (I use the for cycle to develop a working solution, and then slip it to find.)

Serafean
 
Old 11-04-2010, 12:13 PM   #7
serafean
Member
 
Registered: Mar 2006
Location: Czech Republic
Distribution: Gentoo, Chakra
Posts: 903
Blog Entries: 13

Rep: Reputation: 122Reputation: 122
Ok, next time I'll think twice before posting :
Code:
find $directory_name -type f -exec grep -H -o -n "\#\!/bin/bash" {} \; | grep ":1:" | sed 's/:1:.*bin\// /
Sorry for any mystification I may have caused.

Serafean

Last edited by serafean; 11-04-2010 at 12:14 PM.
 
1 members found this post helpful.
Old 11-04-2010, 12:39 PM   #8
GrapefruiTgirl
LQ Guru
 
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594

Rep: Reputation: 551Reputation: 551Reputation: 551Reputation: 551Reputation: 551Reputation: 551
Lightbulb script lister

Hi there!

May I ask, what is the purpose of this script lister project? Is it a school exercise, or a project for the home or what?

If it is not schoolwork/homework, and you just want something to find scripts, then there are many options as you can see above. OP's replies so far indicate that the suggestions offered require some supporting code in order to make the output as you want, to format/filter results in some way, but I'm interested to hear OP's feedback about the latest suggestion(s).

I have some code to offer too, but it's basically a "finished product" -- a couple weeks ago, I wrote a script (lol, a whole script) to do precisely what OP is after right now (though to my own specifications). It is a product of experimentation/boredom/curiosity that I wrote for the sake of writing it, and probably is overkill, but I got carried away. The script is built upon a loop, which loops through directories given on the commandline, uses `find` to find files in there, and uses `awk` for identification as scripts or not, by looking at the shebang. The idea was that it works something like `ls` and since it's a script lister, I called it `sl`, as in /usr/bin/sl. It's mostly almost basically bug-free ;-) but you will find things to improve upon if you want to.

So... If you're doing school work, you will possibly not learn what you're supposed to if I just plop my script down here, and besides, you should be writing your own code if it's homework. :-)

If not school work, I'll post my script and you can try it, or change it, or learn from it, or whatever you like.
 
Old 11-04-2010, 01:23 PM   #9
onsem
LQ Newbie
 
Registered: Nov 2010
Posts: 6

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by serafean View Post
Ok, next time I'll think twice before posting :
Code:
find $directory_name -type f -exec grep -H -o -n "\#\!/bin/bash" {} \; | grep ":1:" | sed 's/:1:.*bin\// /
Sorry for any mystification I may have caused.

Serafean
Thanks a looooooooot. This works fantastic! May I just ask you to explain how the script exactly works?
I understand that the find command searches in entered directory with regular file parameter and executes the grep command. I also understand a bit to the first grep command but I'm not sure about its whole function. Else is a Spanish village to me.:-)

Is there any option how to make it works for more types of searched scripts (shell,awk,perl,.. not only for bash) if I dont wanna make this whole expression for each searched script type again?

Once again thanks a lot

Last edited by onsem; 11-04-2010 at 01:25 PM.
 
Old 11-04-2010, 01:40 PM   #10
onsem
LQ Newbie
 
Registered: Nov 2010
Posts: 6

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by GrapefruiTgirl View Post
Hi there!

May I ask, what is the purpose of this script lister project? Is it a school exercise, or a project for the home or what?

If it is not schoolwork/homework, and you just want something to find scripts, then there are many options as you can see above. OP's replies so far indicate that the suggestions offered require some supporting code in order to make the output as you want, to format/filter results in some way, but I'm interested to hear OP's feedback about the latest suggestion(s).

I have some code to offer too, but it's basically a "finished product" -- a couple weeks ago, I wrote a script (lol, a whole script) to do precisely what OP is after right now (though to my own specifications). It is a product of experimentation/boredom/curiosity that I wrote for the sake of writing it, and probably is overkill, but I got carried away. The script is built upon a loop, which loops through directories given on the commandline, uses `find` to find files in there, and uses `awk` for identification as scripts or not, by looking at the shebang. The idea was that it works something like `ls` and since it's a script lister, I called it `sl`, as in /usr/bin/sl. It's mostly almost basically bug-free ;-) but you will find things to improve upon if you want to.

So... If you're doing school work, you will possibly not learn what you're supposed to if I just plop my script down here, and besides, you should be writing your own code if it's homework. :-)

If not school work, I'll post my script and you can try it, or change it, or learn from it, or whatever you like.

Yes the assignment I have written is a school project. If it would be mine project I would do the searching differently. Also I have seen a lot of different solutions but I needed something to comply the assignment precisely. I was working on the project for a few days then I have came across this problem and my mind got stuck. So I needed some help.
 
Old 11-04-2010, 01:42 PM   #11
GrapefruiTgirl
LQ Guru
 
Registered: Dec 2006
Location: underground
Distribution: Slackware64
Posts: 7,594

Rep: Reputation: 551Reputation: 551Reputation: 551Reputation: 551Reputation: 551Reputation: 551
I understand, thank you for the explanation!

Out of curiosity, how would you do the searching differently, if it were a personal project?

Best of success!
 
Old 11-04-2010, 02:33 PM   #12
serafean
Member
 
Registered: Mar 2006
Location: Czech Republic
Distribution: Gentoo, Chakra
Posts: 903
Blog Entries: 13

Rep: Reputation: 122Reputation: 122
Quote:
May I just ask you to explain how the script exactly works?
I understand that the find command searches in entered directory with regular file parameter and executes the grep command. I also understand a bit to the first grep command but I'm not sure about its whole function. Else is a Spanish village to me.:-)
if you take away the everything but the find command (all after | ), you'll get something like
Code:
./eztvrss/script:1:#!/bin/bash
./eztvrss/rss.awk:1:#!/bin/awk
./eztvrss/rssparse:4:#!/bin/bash
the second grep command filters out any lines not containing :1: (meaning the first grep matched on the 1st line). then sed replaces ":1:#!/bin/" with a space.
Quote:
Is there any option how to make it works for more types of searched scripts (shell,awk,perl,.. not only for bash) if I dont wanna make this whole expression for each searched script type again?
yes, you can match to this regex :
Code:
\#\!/bin/\(awk\|bash\)
which matches bash and awk scripts. You can add as many types as you want.
 
Old 11-08-2010, 06:24 PM   #13
onsem
LQ Newbie
 
Registered: Nov 2010
Posts: 6

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by serafean View Post
if you take away the everything but the find command (all after | ), you'll get something like
Code:
./eztvrss/script:1:#!/bin/bash
./eztvrss/rss.awk:1:#!/bin/awk
./eztvrss/rssparse:4:#!/bin/bash
the second grep command filters out any lines not containing :1: (meaning the first grep matched on the 1st line). then sed replaces ":1:#!/bin/" with a space.
yes, you can match to this regex :
Code:
\#\!/bin/\(awk\|bash\)
which matches bash and awk scripts. You can add as many types as you want.
And may I ask you how can I change the script if the scrtips wouldnt be just in e.g.:#!/bin/bash but also in #!/local/bin/bash and #!/usr/local/bin/bashand and other directories?

Thanks

Last edited by onsem; 11-08-2010 at 06:33 PM.
 
Old 11-09-2010, 03:13 AM   #14
martinbc
Member
 
Registered: Jun 2010
Distribution: Ubuntu, played with Puppy Slitaz & OpenSUSE
Posts: 40

Rep: Reputation: 4
Hi

What you need to know about regexs is that some symbols have special meanings.

[] create a group which will match a character so [abcd] will match a single character in the string which is one of a,b,c or d; if you wanted to match any lower case letter you could use [a-z]

If the first character in [] is a ^ that means match any character which is not listed so [^a-zA-Z] will match anything except a letter.

You can have wildcard repeats using * (for any number of matching characters) + (more than one character) or ? (zero or one character)
So [^a-zA-Z]* would match any sequence of characters which does not include a letter.

Hope these help you

Martin

Last edited by martinbc; 11-09-2010 at 03:15 AM. Reason: Improve clarity of meaning
 
Old 11-11-2010, 09:08 AM   #15
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 9,250

Rep: Reputation: 2684Reputation: 2684Reputation: 2684Reputation: 2684Reputation: 2684Reputation: 2684Reputation: 2684Reputation: 2684Reputation: 2684Reputation: 2684Reputation: 2684
Well you may still need to play around with scripts that have options after the interpreter on the first line, like awk scripts:
Code:
#!/usr/bin/awk -f
But the following slight change should get your other scripts and not print files without an interpreter:
Code:
find $directory_name -type f -exec grep -H -o -n '#!.*' {} \; | sed -n '/:1:/s@:.*/@ @p'
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Variables and Mkvextract in a bash script and a good resource for bash help? gohmifune Linux - General 9 04-13-2011 09:37 AM
passing variable from bash to perl in a bash script quadmore Programming 6 02-21-2011 05:11 AM
[SOLVED] Using a long Bash command including single quotes and pipes in a Bash script antcore Linux - General 9 07-22-2009 12:10 PM
Strange if statement behaviour when using bash/bash script freeindy Programming 7 08-04-2008 07:00 AM
Bash script to create bash script jag7720 Programming 10 09-10-2007 08:01 PM


All times are GMT -5. The time now is 12:35 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration