mdfind - xargs syntax

Before I waste too much time on this, will someone point out what is wrong with this:

This works:

set targetEmails to paragraphs of (do shell script "mdfind -onlyin ~/Library/Mail '(kMDItemContentCreationDate >= $time.today(-3) && kMDItemKind == \"Mail Message\")'")

I am trying to pipe the list to get the name of each message (128609.emlx or 128609 even better)

set targetEmails to paragraphs of (do shell script "mdfind -0 -onlyin ~/Library/Mail '(kMDItemContentCreationDate >= $time.today(-3) && kMDItemKind == \"Mail Message\")' | xargs basename {}")

I am getting strange results:

Hello.

I don’t think xarg is especially fond of spaces, and I think that goes for basename as well. But what you can do, is use the −0 argument with xargs, and mdfind, so that you get the whole name, and then maybe pipe the result into a file, and there strip off what basename should have stripped off, if you can’t get basename to work.

You will notice in my second script that I am using xargs with -0

This seems to work…

set targetEmails to paragraphs of (do shell script "mdfind -onlyin ~/Library/Mail '(kMDItemContentCreationDate >= $time.today(-3) && kMDItemKind == \"Mail Message\")' | while IFS= read -r path; do echo \"${path##*/}\"; done")

Hello.

Glad you found a solution, sometimes it can be pesky. Regarding your second script: you’ll have to use with xargs too, if you use it with mdfind, or xarg isn’t noticed about nul - separated arguments, but continues to interpret them as it usually does.

What McUsrII’s saying is that you have to use -0 options with BOTH mdfind and xargs. Your second script only specifies one for mdfind.

Hi Nigel. Thanks for pointing that out… I have stared at this too long. McUsr, thanks for the answer.

Besides producing an incorrect first item of {} , this produces the desired results as well.

set targetEmails to paragraphs of (do shell script "mdfind -0 -onlyin ~/Library/Mail '(kMDItemContentCreationDate >= $time.today(-3) && kMDItemKind == \"Mail Message\")' | xargs -0 basename {}")

Hello.

I am sorry I was so unclear, I was on my way to sleep, as I wrote the reply.

You can’t really expect mdfind and xargs to act sanely on filenames only consisting of “{}”. :slight_smile:

By the way: Thanks for the link to Peteris Krumins blog, I have had a look at the blog, and not just the one liners, and there are tons of good info there. :slight_smile:

All of the results of the first script were properly formatted paths, I don’t see where the {} came into play.

It looks as if it should be omitted from the xargs argument: “xargs -0 basename”.

Thanks Nigel, Perfect

set targetEmails to paragraphs of (do shell script "mdfind -0 -onlyin ~/Library/Mail '(kMDItemContentCreationDate >= $time.today(-3) && kMDItemKind == \"Mail Message\")' | xargs -0 basename")

That means when not using the option -0 in xargs, file names containing spaces, tabs or newline will split into multiple arguments and eventually result in an error. The option -0 on both ends is the only safe way to make sure that the file names are send correctly to the command. A null character can’t be stored in a file name and therefore you don’t have to worry about this character in file names.

Too bad that the mdfind command has an exec function like find command so you don’t need to send the results to another xargs but execute them directly with find.

It’s just optional, with the curly braces “{}” you indicate the position of the argument from stdin inside the command. You can even use it more than once. By default it’s added to the end of the line. This is not documented in the manual page of xargs (Snow Leopard) but the man page says it’s according to posix 2; it should be working that way if it wants to be posix 2.

Thanks, DJ. It’s not documented in xargs’s man page in Mountain Lion either, which is still the one from 2004. “{}” is however documented in find’s man page in connection with find’s -exec primary.