PDA

View Full Version : [SOLVED] How to use grep and find together



bcooperizcool
January 25th, 2011, 12:18 AM
How do I use grep with find?

eg


while read names;
do find /private/var/stash/Applications -iname "$names" | xargs grep "^/var/mobile/Applications.*\.app$" | sort | uniq > file.txt
done < otherfile.txt

it doesn't output it right. it prints an error on the screen of "^/var/mobile/Applications.*" -- no such file or directory.

By reading this you should know what I want to do. (Have it only put the lines that start with /var/mobile/Applications, and end with .app into the file.txt)

Thanks!

geirha
January 25th, 2011, 02:02 AM
If the file containing the patterns isn't too long, you could read it into an array, and just use one find command.



# BASH
args=()
{
IFS= read -r name && args=( -iname "$name" )
while IFS= read -r name; do
args+=( -o -iname "$name" )
done
} < otherfile.txt

if (( ${#args[@]} )); then
find /private/var/stash/Applications \( "${args[@]}" \) -exec grep '^/var/mobile/Applications.*\.app$' {} \; | sort -u > file.txt
fi

bcooperizcool
January 25th, 2011, 02:16 AM
It is generated by another part of my script each run, so I don't know how long it is each time.

here is my code so far. (far from perfect. Might have some things I haven't fixed yet, still testing to make it work.) You can see where it generates the file it reads



#!/bin/bash

#Brian Cooper (bcooperizcool)
#This is a completly new script, which shall have better coding. Yes, I will copy parts of the old script to save time ;P

clear
#checks if user is root
if [ `id -u` != 0 ]; then echo "Needs to be run as root(su)(pass = alpine)! (silly person)"; exit 0; fi

#changable for me, so I can test on different machines
base=/var/stash

theme_base=/var/stash/Themes



clean_theme()
{
echo "###########~~~~~~Restoring old icons~~~~~~#############";
while read cleanthird; do
if [[ -e "$cleanthird/icon1.png" ]];
then mv "$cleanthird/icon1.png" "$cleanthird/icon.png";
fi
done < $theme_base/.locations.txt

while read locationclean; do
if [[ -e "$locationclean/icon1.png" ]];
then mv "$locationclean/icon1.png" "$locationclean/icon.png";
fi
done < $theme_base/.system.txt
echo "##########~~~~~~Done~~~~~~#########"
}

new_install()
{
#This should be run with the iComplete theme. Oops... I just realized you need to manually remove this after the #iComplete then install. I'll put it in the video. Sigh....
#AppStore/iTunes.
while read names;
do find /private/var/stash/Applications -iname "$names" | xargs grep "^/var/mobile/Applications.*\.app$" | sort | uniq > file.txt
done < otherfile.txt

}


install_theme()
{

#My way more efficient code for images. AppStore apps too :)

if [[ -d "$theme_base/$theme/Icons" ]];
then ls "$theme_base/$theme/Icons" | sort | uniq > $theme_base/.icons.txt
else echo "Why would you use a theme that doesn't have icons???";
fi

sed 's/.png//' < $theme_base/.icons.txt > $theme_base/.names.txt;
new_install
#System/Jailbreak icons
while read -u1 -r location && read -u2 -r icon; do
if [[ -e "$location/icon.png" ]];
then mv "$location/icon.png" "$location/icon1.png"; echo "Backing up icon for $icon"; cp "$theme_base/$theme/Icons/$icon.png" "$location/icon.png"; chmod 777 "$location/icon.png";
fi
done 1< $theme_base/.system.txt 2< $theme_base/.systemnames.txt


#AppStore/iTunes icon :D
while read -u1 -r folder && read -u2 -r file; do
if [[ -e "$folder/icon.png" ]];
then mv "$folder/icon.png" "$folder/icon1.png"; echo "Backing up icon for $file"; cp "$theme_base/$theme/Icons/$file.png" "$folder/icon.png"; chmod 777 "$folder/icon.png";
fi
done 1< $theme_base/.locations.txt 2< $theme_base/.thirdparty.txt

}

#Time to set the folder it all works out of! :D

echo "Please choose a theme. It is case sensitive, so please type it out exactly" #saves me a lot of coding, as this can now be used as part of the path :3

#echoing the choices, with the variable we set at the top.
echo "-----------------"
ls $theme_base
echo "normal"
echo "-----------------"
read -p "Theme to apply = " theme
echo

if [[ "$theme" == normal ]];
then clean_theme;
else clean_theme; install_theme;

fi

geirha
January 25th, 2011, 02:47 AM
Well, otherfile.txt is not generated anywhere in that code. Also, what's the point of all those txt files you're writing to and reading from?

And a more alarming question, why are you hijacking stdout and stderr in those while loops? You even try to echo something to stdout after hijacking stdout to be an input fd.

bcooperizcool
January 25th, 2011, 05:17 AM
otherfile.txt was just an example b/c I couldn't remember what I had used.
I'm reading from all these files because I don't know the contents of each folder at each run. I actually found a better way to do it by accident, without all that horrendus mess. I would post it, but I'm on my iPhone, and don't have access to it.

Ehehheee.... What? Is that bad? (I have only a vauge clue as to what these are. I'm learning as I go. I only have the basic knowledge of bash. This is my first script...)

geirha
January 25th, 2011, 05:57 AM
Haven't you noticed the "Bad file descriptor" errors when it runs echo inside those while loops? echo writes to FD 1 (stdout), but you redirected FD 1 (for that loop, it goes back to normal afterwards) from a file, so echo is trying to write to a file opened for reading.

Just create two new FDs, 3 and 4 for that purpose.

Anyway, regarding the better way, I hope it involves arrays...?

bcooperizcool
January 25th, 2011, 07:02 AM
No, I never got any errors o.0 (Im assuming I should have)
No arrays, but it doesn't write something it's reading (actually, thinking back to my code, was it sed that wa doing that?). It makes files by find.
Also, thank you for not just saying go read up on bash scripting fro
the start, you actually are helping! (regaurdless of my lack of knowledge in this area, I should probaly read up anyway.). So thank you!

geirha
January 25th, 2011, 07:22 AM
I meant like this


$ while read -u1; do echo something; done 1<<< "a line"
bash: echo: write error: Bad file descriptor


However, it just occurred to me that that error message is of course written to stderr (FD 2) ... which you also "hijacked".

So let me rephrase the question: Haven't you noticed that nothing is printed from the echos inside those while loops? ;)

bcooperizcool
January 25th, 2011, 07:31 AM
Now that you mention it, yes D:
how would I go about fixing that? I can post my updated code tomorow (it might not error. I think I changed that part). Is this bad? Everything else except for the echo works fine! It copie/renames everything where it should go. (my update code.) I just don't remember if it echos or not. :/

geirha
January 25th, 2011, 09:51 AM
Yes, as I said, use unused file descriptors (file descriptors range from 0-255 inclusive, with 0-2 being the standard ones), so 3 and 4 instead of 1 and 2.

One more thing about your code. It's very oddly indented, and thus very hard to read. Bash can output functions in a fairly nice indented way. For example, copy/paste your install_theme function into an interactive bash shell, then run "type install_theme" and bash will output the function code indented. Try to keep this style of indentation, or at the very least be consistent with indentation.


$ type install_theme
install_theme is a function
install_theme ()
{
if [[ -d "$theme_base/$theme/Icons" ]]; then
ls --color=auto "$theme_base/$theme/Icons" > "$theme_base/.icons.txt";
else
echo "Why would you use a theme that doesn't have icons???";
fi;
sed 's/.png//' < $theme_base/.icons.txt > $theme_base/.names.txt;
new_install;
while read -u3 -r location && read -u4 -r icon; do
if [[ -e "$location/icon.png" ]]; then
mv "$location/icon.png" "$location/icon1.png";
echo "Backing up icon for $icon";
cp "$theme_base/$theme/Icons/$icon.png" "$location/icon.png";
chmod 777 "$location/icon.png";
fi;
done 3< $theme_base/.system.txt 4< $theme_base/.systemnames.txt;
while read -u3 -r folder && read -u4 -r file; do
if [[ -e "$folder/icon.png" ]]; then
mv "$folder/icon.png" "$folder/icon1.png";
echo "Backing up icon for $file";
cp "$theme_base/$theme/Icons/$file.png" "$folder/icon.png";
chmod 777 "$folder/icon.png";
fi;
done 3< $theme_base/.locations.txt 4< $theme_base/.thirdparty.txt
}


See? and now I suddenly noticed your chmod commands there. chmod 777 is something you should never do. Why do you think you need to do that?

bcooperizcool
January 25th, 2011, 03:48 PM
Ohhhh... Thank you! I didn't know that was what 1,2,3,4 were! So don't use 1,2 at all right? Also, maybe a little off-topic, but where I used cleanapp and app in the while loop, would it be ok to just leave it? So they are both the same? Or is it safer to have them different names?. About the indent code, I had tried to do it while typing, but I guess that didn't go so well :/. I'll do that in a couple of hours. Thanks for putting upwith all my noob questions!
The chmod is there b/c the icons don't backup/restore right if that isn't done, and the iPhone doesn't always read them right.

geirha
January 25th, 2011, 07:19 PM
Ohhhh... Thank you! I didn't know that was what 1,2,3,4 were! So don't use 1,2 at all right?
It's often useful to redirect FDs 0, 1 and 2. This was just not the case with those while-loops.



Also, maybe a little off-topic, but where I used cleanapp and app in the while loop, would it be ok to just leave it? So they are both the same? Or is it safer to have them different names?
I don't see any cleanapp or app in the code.


The chmod is there b/c the icons don't backup/restore right if that isn't done, and the iPhone doesn't always read them right.
Setting mode 777 most likely makes it work, yes, but that doesn't mean it's a good idea, or that there are no better ways. You should read up on how permissions work when you have the time, so you can set some sane ownership and permissions on it. http://mywiki.wooledge.org/Permissions

bcooperizcool
January 25th, 2011, 07:55 PM
Oh... I'll read up on that at some point! :)

Oops :P I couldn't read that far down on the code with my iphone.
I mean is it ok to say


while read something; do
echo $something
done < somefile

while read something; do
locate $something
done < somefile

So they both have the same thing they are referring to, but each do different functions? Like is it ok to use the same name for it in differnt loops that do different things?

geirha
January 25th, 2011, 08:23 PM
Yes, that's perfectly fine.

Though you should double quote expansions, otherwise bash will attempt word-splitting and glob-expansion, which may cause odd results in certain circumstances.



echo "$something" # instead of echo $something
locate "$something" # instead of locate $something

bcooperizcool
January 25th, 2011, 08:46 PM
Ok! Thank you! I think you have answered all my questions, plus more ;P