How to collect all media file in a mac directory structure?

Posted on

QUESTION :

I’m trying to copy all media files (Mac file type of Image or Movie) to the same directory structure, only taking media files.

  1. Is there a more efficient way than what I’ve got below?
  2. Is there a mechanism in Mac OS find to get the type of Image or Movie?
  3. Can this be done without an intermediate tar file? (assume 100,000 media files)

Idea is to:

  1. Create temporary file list of media files (tar can’t take that many files at command line)
  2. Create tar file
  3. Extract tar file

Thanks for any advice.

# $1 is the directory to search for media
# $2 is the output file name
media_list() {
  find $1 -type f ( -iname "*.JPG" -o -iname "*.JPEG" -o -iname "*.NREF" -o -iname "*.TIFF" -o -iname "*.wmv" -o -iname "*.MOV" -o -iname "*.mp4" -o -iname "*.MPG" -o -iname "*.AVI" -o -iname "*.3g2" -o -iname "*.3gp" -o -iname "*.m4v" ) > $2
}

# $1 is the directory to get media
# $2 is the output tar file name
tar_media() {
  rm file-list.txt
  media_list $1 file-list.txt
  tar -cv -f $2 -I file-list.txt 
}

ANSWER :

Different options:

mdfind -onlyin . 'kMDItemContentTypeTree=public.movie||kMDItemContentTypeTree=public.image' | parallel cp {} /tmp/{/}

  • parallel can be installed with brew install parallel
  • {/} is the basename

find . -iname *.mkv -o -iname *.jpg | while IFS= read -r f; do cp "$f" /tmp/"${f%%*/}"; done

  • read strips characters in IFS from the start and end of lines
  • read -r disables interpreting backslashes
  • ${f%%*/} removes the longest */ pattern from the start

shopt -s globstar extglob nocaseglob; for f in **/*.@(mkv|jpg); do cp "$f" "/tmp/${f%%*/}"; done

  • globstar (added in bash 4.0) makes ** match multiple levels of directories
  • extglob adds support for @(pat1|pat2) (exactly one)
  • nocaseglob makes globs case-insensitive

f() { cp "$1" "/tmp/${1%%*/}"; }; export -f f; gfind . -regextype posix-extended -iregex '.*.(mkv|jpg)' -print0 | xargs -0 -n1 bash -c 'f "$1"' _

  • OS X’s find doesn’t support extended regex, so the command uses GNU find
  • export -f and bash -c are needed to run the function with xargs
  • xargs -n1 takes one argument at a time

Leave a Reply

Your email address will not be published.