Modifying kMDItemLastUsedDate

Discussion in 'Mac Programming' started by Denarius, Jan 28, 2010.

  1. Denarius macrumors 6502a

    Denarius

    Joined:
    Feb 5, 2008
    Location:
    Gironde, France
    #1
    Hi there,

    One of the threads in the OSX area was asking if it's possible to remove items from the today, yesterday and last week canned searches in the sidebar of all of the finder windows. I had a look at the XML and it queries the spotlight metadata for kMDItemLastUsedDate.

    What I'd like to know is if there's anything in the cocoa framework (or maybe somebody has already made an app) to insert a fake value for kMDItemLastUsedDate into the metadata.

    I have tried looking, but although I've done a little Cocoa programming I'm not really sure where to look.
     
  2. Denarius thread starter macrumors 6502a

    Denarius

    Joined:
    Feb 5, 2008
    Location:
    Gironde, France
    #2
    Well, I've now discovered a terminal command called xattr that I can use to see the extended attributes, so I thought I'd start with an image file on an HFS+ volume.

    Code:
    xattr image.jpg
    The only metadata it returns is

    Code:
    com.apple.metadata:kMDItemWhereFroms
    Given that this file exists in the history, it must have an associated kMDItemLastUsedDate so where is it?
     
  3. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #3
    Try mdls on your file rather than xattr.

    Extended attributes are completely different from metadata. Xattrs are attached to the file, stored as part of the file-system. Metadata is extracted from the file, stored in the metadata store (essentially, Spotlight's database). Some xattrs are extracted and stored in the metadata store, but they're still two separate things.

    The commands that operate on metadata fit the 'md*' globbing pattern: mdfind, mdls, mdutil, etc.

    Whatever downloaded your file wrote the xattr on it at that time, for the scanner (mdimport) to pick up later. If that xattr hadn't been written, mdimport wouldn't have it. For example, use 'curl' to download something, and see if it writes the xattr.
     
  4. Denarius thread starter macrumors 6502a

    Denarius

    Joined:
    Feb 5, 2008
    Location:
    Gironde, France
    #4
    Two different things, thank you for pointing that out and mdls showed the value.

    Right, I've looked at the md commands and can't seem to spot anything about updating a value, which seems reasonable as most of these are things that you'd only expect the system to update in normal practices. That said if there is a way of updating kMDItemLastUsedDate either through a terminal command or with a Cocoa function then I'd be interested.

    I've created an Applescript that does what I intended it to by using gzip, which doesn't support os x metadata so it's all lost by zipping and unzipping, but it's rather clumsy.

    Applescript in this thread, the last script posted.
     
  5. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #5
    You generally don't get to update any of the metadata values. This is by design, from what I can see by looking at the low-level API.

    It's possible that one could write a metadata importer that removed last-access times. That's just a thought, not even a hypothesis. There's sample code for importers, and the API is well-defined, so some poking around might give an answer.


    Regarding your AppleScript, the following idiom has a subtle latent problem:
    Code:
    ... & "'" & posixPath & "'"
    
    If the posixPath contains any single-quotes, then the quoting will fail. For example, a pathname of "/Users/foo/Documents/This won't work" will, um, not work.

    You have to replace every instance of apostrophe (single-quote) in the posixPath with the sequence apostrophe-backslash-apostrophe-apostrope ('\''). Then put one apostrophe on each end of the resulting string.

    It's a complex enough operation that you should just do it once, rather than repeating it for each 'do shell script ...' command.

    Oh, and you could probably write two commands in a pipeline and avoid the temp gzip-file. E.g. gzip ... | gunzip ...

    You'd still need a temp outfile, because you can't overwrite the original if it's the source of the data.
     
  6. Denarius thread starter macrumors 6502a

    Denarius

    Joined:
    Feb 5, 2008
    Location:
    Gironde, France
    #6
    Replacing the quotes is no problem, I'll change it later, but I'm a tiny bit uncertain about piping in that context.

    Are you saying

    Code:
    gzip filename | gunzip filename.gz
    I can see that having Applescript doing less can only be a good thing though!
     
  7. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #7
    Not exactly that. Use the gzip option -c to tell it to write compressed output to stdout. On the receiving side, take a look at the -n and -N options, because you'll want to tell it to ignore the embedded name and write to a uniquely named temp-file. Effectively, it's setting up a pipe with gzipped data being sent through.

    On the output side, it must write to a unique file. On success, you can mv that file (rename it) to replace the original.

    Now that I think about it, though, how is this really any different than:
    Code:
    cat somePath >somePath.tmp && mv somePath.tmp somePath
    
    I think this basic approach might have other problems, such as losing resource-forks. Try it on an alias-file, which is entirely resource-fork and no data-fork. If it fails, then you need a different command.

    One command I know handles resource-forks is ditto. It should also be xattr-aware, IIRC.
     
  8. Denarius thread starter macrumors 6502a

    Denarius

    Joined:
    Feb 5, 2008
    Location:
    Gironde, France
    #8
    I loved the cat idea. Tried it, but it still had it's metadata intact at the end. Got the apostrophe problem sorted though.
     
  9. Denarius thread starter macrumors 6502a

    Denarius

    Joined:
    Feb 5, 2008
    Location:
    Gironde, France
    #9
    Hi chown,

    Thought you might like to know that I've redone it using ditto --norsrc rather than the gzip having been prompted to look for a more streamlined solution by your suggestion.

    I've posted the script here.
     

Share This Page