0

I did a good bit of searching and testing on my own, but I can't seem to find the best way to achieve this goal. I would like to have a bash one liner that will find a script on the machine, execute the script and have the ability to add switches or needed information in my case to execute the script successfully.

To get a little more specific, I am in Kali Linux and I run the locate command like so:

locate pattern_create

which returns:

/usr/share/metasploit-framework/tools/pattern_create.rb

So I thought about piping this into xargs to run the script like so:

locate pattern_create | xargs ruby

but of course I could not specify the options I need to that would run the script successfully, which would be:

ruby /usr/share/metasploit-framework/tools/pattern_create.rb 2700

I came up with a work around, but I feel that it's somewhat sloppy and this could be done easier, and that's where I hope I could get any input/feedback.

I found out I can run:

pattern_create=$(locate pattern_create) && ruby $pattern_create 2700

to get exactly what I need, but then I am dealing with environment variables which I would not want a bunch of when doing this often. I was hoping to figure this out with xargs or maybe and even cleaner way if possible. I know this can be done easily with find -exec, but that won't work in my case where I don't where the script is stored.

Any help would be awesome, I appreciate everyone's time. Thank you.

Matthew
  • 3
  • 2

2 Answers2

0

You can do:

ruby $(locate pattern_create)

But be aware that if there are multiple lines returned by locate, then this may not do what you wanted.

P.P
  • 117,907
  • 20
  • 175
  • 238
  • This is perfect! I understand the caution when issuing this command. My thoughts were to verify that the script is there and I recognize it `locate `, then `↑` back to `locate `. Next, rewriting the command with your suggestion and adding the needed arguments. Ultimately I was piping that into xclip like so: `ruby $(locate pattern_create) 2700 | xclip -selection c` – Matthew Jan 21 '16 at 15:28
  • @Matthew Your approach is fine, IMO. If you just don't want to have variables in your environment, you can *unset* it: `var=$(locate pattern_create) && ruby $var 2700 ; unset var`. Also , be aware that `locate` uses a database which may not have upto date info. It may even fail to find a file that actually exists on your system. `find` command is a better choice. – P.P Jan 21 '16 at 15:42
  • Is there a better way to use find when you are unsure of the exact path? I wasn't sure if find had that capability or not. – Matthew Jan 21 '16 at 15:51
  • You can specify `/`: `find / -name foobar`. But it's going to be slow. Generally, it's slower than `locate` since it searches through the filesystem. But `find` is more accurate. If you know there's only one file and then you can quit after first match with GNU find: `find / -name pattern_create 2>/dev/null -print -quit`. – P.P Jan 21 '16 at 15:53
  • Awesome! I really appreciate all the help. Thanks a lot. Quick question, is the `ruby $(locate pattern_create) 2700 | xclip -selection c` command creating a variable or does it just hold that value for the time being? – Matthew Jan 21 '16 at 15:59
  • Sorry to re-comment, but I didn't think you would see my edited comment above. for the `ruby $(locate pattern_create) 2700 | xclip -selection c` command, is that creating a variable or does it just hold that value for the time being? I was not 100% certain, as I see ruby then the path and so on, but nothing giving the "$(locate pattern_create)" a variable. – Matthew Jan 21 '16 at 16:23
  • `ruby $(locate pattern_create) 2700 | xclip -selection c` doesn't introduce any variable at all. But if `locate` doesn't find anything then the first argument to `ruby` will be empty, which is equivalent to: `ruby 2700 | xclip -selection c`. So you may want to handle that possibility. – P.P Jan 21 '16 at 16:34
0

This is a dangerous thing to do as you do not know what locate will return and you could end up executing arbitrary scripts. I suggest that you use an intermediate script which will protect against the unexpected, such as finding no scripts or finding more than one.

#! /bin/sh
#
if [ $# -eq 0 ]
then
    echo >&2 "Usage: $0 script arguments"
    exit -1
fi
script=$(locate $1)
numfound=$(locate $1 | wc -l)
shift
if [ $numfound -eq 1 ]
then
    # Only run the script if exactly one match is found
    ruby $script $*
elif [ $numfound -eq 0 ]
then
    echo "No matching scripts found" >&2
    exit -1
else
    echo "Too many scripts found - $script" >&2
    exit -1
fi
Neil Masson
  • 2,609
  • 1
  • 15
  • 23
  • Very nice! This is definitely handy, I appreciate this. My only thought behind the one liner was when I already issued the `locate ` command and verified the results. Then running a one liner to execute that script with some arguments. – Matthew Jan 21 '16 at 15:16
  • If you are verifying the `locate` then I would cut and paste the result - double-left click, middle-click IIRC. There's nothing faster! – Neil Masson Jan 21 '16 at 15:26
  • True! That is definitely quick, I have to keep that in mind. Thank you sir! – Matthew Jan 21 '16 at 15:48