Search code examples
bashmacosterminallsglob

Pattern matching on bash for screen shots on macOS


I'm having a hard time trying to put together a globbing expression to match the screen shot file name patter on macOS.

I've managed to get the following regex to do the job:

Screen Shot \d{4}-\d{2}-\d{2} at \d{2}\.\d{2}\.\d{2}( \(\d+\))?\.png

This regex matches:

Screen Shot 2017-04-04 at 23.11.22.png
Screen Shot 2017-04-04 at 23.38.40 (2).png
Screen Shot 2017-04-04 at 23.38.40 (12).png
Screen Shot 2017-04-04 at 23.38.40 (12342).png

The closest I've got is the following, that matches everything except the screen shots taken at the same second, the ones with the (number) inside:

Screen\ Shot\ [0-9][0-9][0-9][0-9]\-[0-9][0-9]\-[0-9][0-9]\ at\ [0-9][0-9].[0-9][0-9].[0-9][0-9].png

I've started testing *?\ \([0-9]\).png and it works but I couldn't join both expressions because once I did, the result is no such file or directory

The idea is to create an alias to remove all the screen shots, like:

alias clrss="cd ~/Desktop | rm -rf Screen\ Shot*.png"


Solution

  • you tried this:

    alias clrss="cd ~/Desktop | rm -rf Screen\ Shot*.png"
    

    that doesn't work because | sends the output of one command to the next command, whereas ; is for separating sequential commands, so ; works there:

    alias clrss="cd ~/Desktop ; rm -rf Screen\ Shot*.png"
    

    also, the -r is for removing directories and their contents, which is useless because there won't be any directories named Screen Shot*.png:

    alias clrss="cd ~/Desktop ; rm -f Screen\ Shot*.png"
    

    but that command will leave you on the Desktop, so this is better:

    alias clrss="rm -f ~/Desktop/Screen\ Shot*.png"
    

    but, if you're worried about matching Screen\ Shot*.png matching too much, it would make sense to use a somewhat more specific pattern, e.g.:

    alias clrss="rm -f ~/Desktop/Screen\ Shot\ [0-9][0-9][0-9][0-9]\-[0-9][0-9]\-[0-9][0-9]\ at\ [0-9][0-9].[0-9][0-9].[0-9][0-9]*.png"
    

    or, if that's still too general, you could use grep with your perl regular expression and xargs rm, like this:

    alias clrss="find ~/Desktop -name \"Screen Shot *.png\" |
      grep -P 'Screen Shot \d{4}-\d{2}-\d{2} at \d{2}\.\d{2}\.\d{2}( \(\d+\))?\.png' |
      tr '\n' '\0' |
      xargs -r -0 rm -f"
    

    UPDATE from @alcanaia: on MacOS, use grep -E instead of grep -P and use xargs -0 instead of xargs -r -0.

    UPDATE 2 from @alcanaia: here's a better regex; it includes 12h format and an edge case:

    Screen Shot \d{4}-\d{2}-\d{2} at \d{1,2}\.\d{2}\.\d{2}( (AM|PM))?(( (\d)?\(\d+\))| \d)?\.png