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

Posted on


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 


Different options:

mdfind -onlyin . '||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.