Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

Bash 'find' bug

-

My Bash manual for 'Find' says:


'-depth Always true; same as the -d option.'


My experience is that -depth works but -d does not.


Is this a known issue?


If not can others confirm this behaviour?


-

Mac OS X (10.5.8), Two 733 MHz G4s with Leopard !

Posted on Apr 24, 2012 3:06 PM

Reply
20 replies

Apr 24, 2012 5:19 PM in response to Neville Hillyer

Could be a bug, or it could be a command syntax error. Please post the particular find command you are testing; the -d syntax is a slightly weird one, as it can be both an option, and a primary. (With that command, somebody here can also test it against something newer than 10.5, too.)


My preference on OS X is mdfind over find. The mdfind command syntax is (yet) more cryptic (than find), but it's gonzo-fast; it's the command-line interface into Spotlight.


And in general, bash command syntax does vary somewhat by platform, and by the version of the particular tool. Use the man page to determine the particular syntax for the particular platform. And there are the occasional bugs.

Apr 24, 2012 5:31 PM in response to Neville Hillyer

I got identical results using


/usr/bin/find -d path >tmp.1
/usr/bin/find path -d >tmp.2
/usr/bin/find path -depth >tmp.3


And I got different results from the above using


/usr/bin/find path >tmp.4

cksum tmp.[1234]
2923241020 29127374 tmp.1     # match
2923241020 29127374 tmp.2     # match
2923241020 29127374 tmp.3     # match
618095947 29127374 tmp.4      # different


So I cannot reproduce any errors.


The above was a 10.7.3 system


Using a 10.5.8 system


cksum tmp.[1234]
4233427378 28718 tmp.1     # match
# the find path -d option was not valid; must be something newer than 10.5.8
4233427378 28718 tmp.3     # match
2987672313 28718 tmp.4     # different


Message was edited by: BobHarris

Apr 25, 2012 5:33 AM in response to Neville Hillyer

The version of bash has nothing to do with the 'find' command. They are 2 separate programs.


"find /bin -d ..." syntax is not supported in the Mac OS X 10.5.8 'find' command.


That syntax "IS" supported in 10.7.3


In 10.5.8, you would need to use


find -d /bin -name bash

or

find /bin -depth -name bash


If staying on Mac OS X 10.5.8 is important, but you also need the "find /bin -d ..." syntax, you could most likely locate the open source 'find' copy and build a newer version for your system. There are also packages such as MacPorts.org and Fink.sf.net which have Mac OS X ported open source packages available.


Personally, I would just avoid the "find /bin -d ..." syntax, as there are valid work arounds.

Apr 25, 2012 8:04 AM in response to BobHarris

Thanks Bob.


Clearly inexperience in this area on my part. I don't recall previously coming across commands which have two position sensitive lists of options (albeit one called options and the other expressions / primaries / operands) before and after the path. Is this common? Having consulted the man page again I see that it is correct although I still find the definition: '-depth Always true; same as the -d option' misleading.


My application does not allow me to upgrade my software. I am producing a means of creating new folders on standard Leopard desktops which comply with users' settings rather than inheriting them from the icon based desktop - a common source of annoyance resulting in several historic hacks, all of which (as far as I can tell) rely upon third party software - more on this later hopefully.


Upon reflection it may be better for me to use -depth 1. I don't like 'find' as it always defaults to true, even if nothing is found, but I don't know what else to use to efficiently discover if a directory exists with a particular, name, size and date.

Apr 25, 2012 8:12 AM in response to Neville Hillyer

Is this common?

'find' is in a class all by itself. But it is so useful and powerful, nothing has ever replaced it :-)


If you need to look down a directory tree, then 'find' is the best first pass tool at finding files.


Instead of -depth 0, you could use -prune


if find /bin/bash -prune >/dev/null 2>&1; then
     echo /bin/bash exists
fi


The above form could also include other 'find' selection operators.


If you know the directory, then you can also use


if [[ -d /bin/bash ]]; then
    echo /bin/bash exists
fi


You can use ls -l to capture the time of a file and with different ls options you can choose the modification (default with -l), or the last accessed time (atime), or the last metadata mod time (aka ctime). ls -l can also give you size.


You can also use the 'stat' command to extract various file metadata information, such as time and size information.

Apr 25, 2012 8:35 AM in response to Neville Hillyer

It's not entirely clear what your goal is (you havn't been specific), but if you're trying to find folders on the desktop that conform to particular naming conventions, here's a couple of alternate options to find that you can consider:


use mdfind. (the following finds folders recursively on the desktop whose name begins with 'a'):


mdfind "kMDItemContentType=='public.folder' && kMDItemFSName=='a*'" -onlyin ~/Desktop


use applescript. (the following finds folders non-recursively on the desktop whose name begins with 'a'):


tell application "System Events"

set theFolders to every folder of desktop folder whose name begins with "a"

end tell

Apr 25, 2012 9:34 AM in response to twtwtw

Thanks for both replies.


@ Bob


So far I have got:


$ find -d ~/Desktop -depth 1 -Bmin 1 -empty -iname "untitled folder*" -exec rm -d {} \;


Depth needs to be set to 1. I am searching for directories, I assume this is why prune does not work. I need the -d to inhibit silly error messages unrelated to performance. I have yet to discover how to run the rest of my scripts when folders are found, a following && will not work as find always defaults to true. Perhaps I can put a function call in place of rm, I will try this later. It would be better to reduce Bmin to seconds but this does not look easy.


I have used stat and grep before for files. It is not documented as working for directories but I see that it does. Perhaps not as concise as find for this application.


@ twtwtw


'mdfind' is not described as working for directories in my man page but it clearly does. Does it have the necessary selectors for size and date and depth?


Where practical I prefer 'bash' rather than AppleScript, mainly for speed (launch and execution) but also script size. Having said that my script, which will be contained within a plist, already needs some AppleScript (via osascript) to open folders with the correct settings.

Apr 25, 2012 10:33 AM in response to Neville Hillyer

mdfind has keys for size and date (kMDItemFSSize and kMDItemFSCreationDate or kMDItemFSContentChangeDate - I don't know if they are the 'necessary' ones since you haven't told us what you're doing). You can't specify a particular depth, so far as I know; mdfind always searches the entire hierarchy starting at the folder you specify. you'd have to filter the results if you only wanted it to go to a specific depth. see the query programming syntax and metadata attributes references.


As far as applescript goes - frankly - sometimes it's just easier to do stuff in applescript than in the shell.

Apr 25, 2012 12:12 PM in response to twtwtw

Thanks for the interesting mdfind links - looks very flexible. I only want to search one directory so I could use '-onlyin dir'. Pity my mdfind man gave no clue about the flexibility. This is all it says:


mdfind(1) BSD General Commands Manual mdfind(1) NAME mdfind -- finds files matching a given query SYNOPSIS mdfind [-live] [-count] [-onlyin directory] query DESCRIPTION The mdfind command consults the central metadata store and returns a list of files that match the given metadata query. The query can be a string or a query expression. The following options are available: -0 Prints an ASCII NUL character after each result path. This is useful when used in conjunction with xargs -0. -live Causes the mdfind command to provide live-updates to the num- ber of files matching the query. When an update causes the query results to change the number of matches is updated. The find can be cancelled by typing ctrl-C. -count Causes the mdfind command to output the total number of matches, instead of the path to the matching items. -onlyin dir Limit the scope of the search to the directory specified. -literal Force the provided query string to be taken as a literal query string, without interpretation. -interpret Force the provided query string to be interpreted as if the user had typed the string into the Spotlight menu. For exam- ple, the string "search" would produce the following query string: (* = search* cdw || kMDItemTextContent = search* cdw) EXAMPLES The following examples are shown as given to the shell. This returns all files with any metadata attribute value matching the string "image": mdfind image This returns all files that contain "MyFavoriteAuthor" in the kMDItemAu- thor metadata attribute: mdfind "kMDItemAuthor == '*MyFavoriteAuthor*'" This returns all files with any metadata attribute value matching the string "skateboard". The find continues to run after gathering the ini- tial results, providing a count of the number of files that match the query. mdfind -live skateboard To get a list of the available attributes for use in constructing queries, see mdimport(1), particularly the -X switch. SEE ALSO mdimport(1), mdls(1), mdutil(1), xargs(1) Mac OS X June 10, 2004 Mac OS X (END)

Apr 25, 2012 12:35 PM in response to BobHarris

Thanks Bob.


I can only think that I did a silly test such as:


find ~/Desktop -depth -name "untitled folder*" -prune


As documented this should work although I should have been more circumspect as I was aware of the warning at the end of the following:


-prune This primary always evaluates to true. It causes find to no

descend into the current file. Note, the -prune primary has no

effect if the -d option was specified.


I do wish the man was more accurate. It gave no warning of the incompatibility with the -depth primary. Also it did not mention not descending into the specified directory. I note that often 'file' means files or directories but on other occasions it does not. There appears to be no clues about how specific it is intended to be.

Apr 25, 2012 1:13 PM in response to Neville Hillyer

First of all, my approach of


find ~/Desktop/folder -prune


is better than yours, as my putting the full path in the first argument means find will return an error if the file does not exist.


Your approach has 'find' always returning success.


As for your 2 different find's


In the first, you NEVER process the -prune UNLESS -name folder is TRUE. That is to say your find command looks like:


find ~/Desktop -name folder -a -prune


where -a is AND and only gets invoked if -name folder is true, so you have not invoked -prune until you find a -name folder. The -a is implied between arguments.


In the second, -prune happens first, and stops looking inside of ~/Desktop, so -name folder will never find anything.


After the path argument, every -xxxx argument is assumed to have a -a (AND) between them, unless you specify something like -o. This is why man find constantly says things always return TRUE, because it is important to move on to the next -xxxx aargument.

Bash 'find' bug

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple ID.