Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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 
}
share|improve this question
add comment

1 Answer 1

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
share|improve this answer
    
There's no parallel on OS X by default. It'd also help if you explained what these options do. –  Daniel Beck Jun 16 '13 at 17:49
    
It would be great to list the pros and cons of those, especially with external USB drives with huge numbers of files. –  justingordon Jun 16 '13 at 22:48
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.