How to script moving files up one directory level with Terminal (or BBEdit worksheet)

bashfishphotos.appterminal

When exporting from Photos.app with settings that preserve the album & folder structure, every album folder contains dated folders for every date represented in that album, with the actual images inside those. An example export for this question gives this structure…

Export/
    Colour/
        11 November 2005/
            img_0440.jpg
        13 November 2005/
            pb130006_1_1.jpg
    Life/
        Creatures/
            12 November 2005/
                img_0453.jpg
        People/
            9 November 2005/
                img_0174.jpg
            10 November 2005/
                img_0181.jpg
            14 November 2005/
                pb140009.jpg
        Plants/
            10 November 2005/
                img_0404.jpg
                img_0408.jpg
            13 November 2005/
                img_0477.jpg
            14 November 2005/
                img_0625.jpg

What can I run in Terminal to traverse the contents of Export & move all found files up one directory level?

The desired result on my example would be…

Export/
    Colour/
        img_0440.jpg
        pb130006_1_1.jpg
    Life/
        Creatures/
            img_0453.jpg
        People/
            img_0174.jpg
            img_0181.jpg
            pb140009.jpg
        Plants/
            img_0404.jpg
            img_0408.jpg
            img_0477.jpg
            img_0625.jpg

A solution that works in bash, because I do a lot of my CL stuff in BBEdit which is bash only, or fish because that's my preferred shell in Terminal, would be preferred, but I'll work with other shells.

Best Answer

This is untested: remove the echo if it looks right:

find ./Export -name '*.jpg' -print0 |
  xargs -0 sh -c 'for file; do echo mv "$file" "${file%/*}"/..; done' sh

The odd-looking trailing sh is required because it gets set as $0 in the shell body, so the rest of the arguments fed to it by xargs can be easily iterated.

This will leave the empty directories. To list empty directories:

find . -type d -empty -print

To delete empty directories:

find . -type d -empty -print -delete

To not rely on the file extension:

find ./Export -type f -print0 |
  xargs -0 sh -c '
    for file; do
      case "$(file "$file")" in
        *"JPEG image data"*) echo mv "$file" "${file%/*}"/..;;
      esac
    done
  ' sh