Shell 'Find' ignore files in folders if folders are found too...

Hi everyone,

Sorry for posting so much (this is my second) questions today. This time it’s rather UNIX actually but I’ll still ask it. :confused:

You have a folder “/Test” inside that folder there’s “/Test/Name” (also a folder) and inside “Name” there’s “/Test/Name/Name.file”. If I use

do shell script "find /Test -name Name"

It will give me the folder “Name” not the file “Name.file” in the folder “Name”.
But instead I use regular expressions so I can search for multiple files at once.

do shell script "find -E /Test -iregex '.*Name.*'"

This gives me the folder “Name” and all it’s contents wether they have “Name” in their name or not. How can I just find the folder ? i.e. find “/Test/Name/” and not “/Test/Name/Name.file” ? I don’t mean just finding folders but just ignore there contents…

Okay, I know I probably used too much “name” in this post :wink: but thanks in advance. If one doesn’t understand my question, I’ll try to explain it a bit more clearly without using to much “name”. :slight_smile:

do you mean


do shell script "find /Test -name Name*"

?

No not really, try creating those two folders and file and run both my scripts. I have to use regex because it has to search for multiple files (this isn’t used in the example for the sake of simplicity :slight_smile: )

I don’t want it to find :

"/Test/Name /Test/Name/Name.test/"
I want:

"Test/Name"

so if a folder with in its name the searchterm and in it’s contents too, I want to ignore the contents. But it’s much easier if you create the 2 folders & file.

Thanks for your quick reply Stefan. BTW, your LSFindApp_ppc works great. Haven’t tested it on Panther yet.

Does your specific case preclude the use of -or?

Example:

find . -name 'Name.txt' -or -name 'foo.txt'

Failing that, you might consider a better regex.

I think your simplification is getting in the way of being able to help you. Similar to Stefan’s suggestion, my first thought was “find -name ‘Name’”. You say you need a regex but you do not provide the details someone would need to come up with a general solution that can encompass the details you do not provide!

By the way (as Bruce has also pointed out), find can test disjunctions on expressions (aka OR), so you may not need regex just to test for multiple name variations: find . -name '*This*' -o -name '*That*'

If you want to ˜ignore’ the contents of a directory, you need to “-prune” it. Without knowing more of what you are trying to do though, I can not tell you exactly how to apply “-prune”. It might be something like this: find -E /Test -iregex '.*Name.*' -print -type d -prune

First of all, thank you :wink:
The problem was that I couldn’t quite explain what I wanted, you see, if you have a folder who has the same name as a file within it, do shell script “find /Test -name Name” will just find the folder, not the folder and the file. If you have a folder and the name is the search term but the name of the file differs from it, it will find the folder… but the important thing about this is that it’ll find the folder and doesn’t return the file within it if also matches the search term. By using do shell script “find -E /Test -iregex ‘.Name.’” you will find both the folder and the file within it if they match. This isn’t what I need in the rest of my script. I hope I can explain it a little bit :expressionless: No need for -prune because if you use that you need to know a folder. In this case the folder I’m talking about is returned of the script and is unknown at the beginning. It’s all in the * I think.
This will find both file and folder:

do shell script "find /Test -name Name*"

And this won’t find the file:

do shell script "find /Test -name Name"

Anyway,

find . -name '*This*' -o -name '*That*'

works beautifully. I read here http://www.macscripter.net/viewtopic.php?id=13467 that searching for more than one file requires a regex.

So is there any way that I can filter
“/Test/Name
/Test/Name/Name.zip”
so it becomes
“/Test/Name”

Thanks everyone and sorry for my inconvenience

It seems to me that you want “-prune”. find can decide if something is a folder, you do not need to tell it.

# example usage directly in shell $ find . . ./1 This.txt ./2 That.txt ./3 This dir ./3 This dir/1 This file.txt ./3 This dir/2 That file.txt ./3 This dir/3 Other file.txt ./4 That dir ./4 That dir/1 This file.txt ./4 That dir/2 That file.txt ./4 That dir/3 Other file.txt $ find . \( -name '*This*' -o -name '*That*' \) -print -type d -prune ./1 This.txt ./2 That.txt ./3 This dir ./4 That dir

do shell script "find . \\( -name '*This*' -o -name '*That*' \\) -print -type d -prune"

Yes that’s what I was looking for. I didn’t know I needed prune because I thought it was only to exclude dirs while searching. Sorry I couldn’t explain it very good :wink: The problem is that I’m not that into UNIX, I search for commands and then alter them so they work. But in this case you used some new things like the \ and the -print. I think I’d rather ask this question on a UNIX forum if I later have problems with it…

But thanks a lot everyone, couldn’t explain it completely but somehow it got figured out, I’ll try to explain questions better next time :slight_smile:

That approach seems destined to frustrate you in the long run. I usually find it best to try to learn about the tools involved and what options are available. Searching can be useful to find new tools, but then I would suggest switching to learning about the tool itself instead of trying to apply the example(s) found in the search. You have already seen how that has led you astray in the development of this script: In the post you originally found, the writer said that they did not think there was a way to search for different names without using a regex”that was not true (and probably never has been true, I would be very surprised if the regexp option predated the OR option in find’s history).

In the case of find there are many options available for doing a variety of types of searches. The parameters to find are used to write boolean (true/false) expressions. Using the implicit AND, the -o OR, the ! NOT, and the parenthesis you can create very complex searches. It is a (small) language unto itself and it would be worth it to study the manpage if you plan on using it much more.

Both of those are covered in the manpage. The thing about the double backslash, “\”, is that you want find to get an actual parenthesis, “(”, in its argument list. But parentheses are interpreted specially in the shell, so you have to follow the shell’s quoting/escaping rules. To make the shell pass a parenthesis to find, you can add a backslash before it. Then you need to represent “(” in an AppleScript inline string value. AppleScript’s string quoting rules say that backslash is special and needs to be escaped if you want one in an inline string value, so the AppleScript code becomes “\(”. If instead you decide to use single quoting for the shell instead of a backslash, then no special escaping is needed at the AppleScript level and you end up with “‘(’” (single quote, parenthesis, single quote).

I ran across a couple of shell tutorials recently, they may be worth reading: UNIX SHELL Quote Tutorial and Bourne Shell Tutorial. I have only skimmed over them, but they seem reasonable to me. Edit: When these tutorials were converted from “roff” to HTML, it seems that the backslashes were lost. This makes many of the parts about quoting a bit confusing if you do not already know where the backslashes should go. Also, in several places the Bourne shell material is targeted at the version of sh from Solaris, which is often considered to be a bit buggy. The tutorial demonstrates some of these bugs but does not mention that most modern version of the Bourne shell (bash, dash, probably zsh, too) do things more sanely.

Not a bad idea. There you would find more people that know the general tools, so you would probably get faster responses. Here we can all assume you are using Mac OS X and not bother with what might be slightly different if you were running on some other Unix-type system. We can also suggest tools that are specific to Mac OS X if there is a good match to your problem.

For me, the specific examples helped the most. Sometimes we say “a picture is worth a thousand words”, and that applied in this case to the examples. A full and complete English language description of what you wanted would have been fairly long and complicated, but a full example could be as short as 4-6 short lines.

Well mostly when I use a shell script I first check the man page for all the options, I mostly skim them only… Then I try to make things work, if it doesn’t I’ll search on this forum and if that doesn’t help me I try Wikipedia (it has exmaples most of the time) and then just a Google search. I mostly stop reading the man pages after the options are done. In this case the other part of the man page says something about -or (and a bit further one line saying that -or is the same as -o). I used -o before in the find script before (with prune) but without knowing what the -o means… But other things like -print, I have never used them. I didn’t even know that you could prune with your search results. The hardest shell commands I think for me are the grep/cat ones. It requires much syntax knowledge (which I don’t have, like the "\) and is a combination of several commands. This is rather hard for me to understand.

I still like to use shell commands because they don’t require the Finder or System Events etc. Most of the times I compare them in speed with alternatives. Those tests have so far pointed out that shell scripts are a bit slower than other things. But the difference I’m talking about is like 0.001 second or something like that. These tests aren’t the greatest I guess, there are much variables that I can’t control but it just gives an idea. I’m sure some shell scripts are faster than others and that they are faster in the long run.

Anyway, thanks for the two links, they seem very interesting.