I have nearly 1,000,000 .mp4 security videos stored in a single Mac folder that need to be moved into individual folders by creation date, named "Security Videos MM-DD-YY".

So, for example, all files with the creation date of Feb. 1, 2021 would go into a newly created folder named "Security Videos 02-01-21", etc.

At the end of the process, I would expect to see only a few hundred dated folders inside this original folder, with the million video files distributed into more reasonable groups based on the date.

I had originally intended to do this with Applescript, but as you might imagine, it times out and basically chokes the entire laptop. I am told a bash script run from Terminal will do the trick, but I am completely unfamiliar with how to write that.

  • What sort of names do the files have? Do the name include date and/or time? Do the file themselves contain any meta-data about when they were recorded? Or must we use the filesystems modified/created-time of the file? Feb 7 at 15:31
  • The files are named in this format: "2021/02/01 | 00_03_07.mp4" but they also have standard filesystem creation/modification dates that match. So any one of the these three methods can be used to extract the date and assign them to the proper folders. Feb 7 at 15:38
  • 3
    Consider using a YYYY-MM-DD date format. It's always nice if the listing by filename is already sorted by date.
    – Freddy
    Feb 7 at 16:02
  • Yes, I think you're right with that, so let's use the YYYY-MM-DD format. Thanks for the advice, now if someone can help with the script :-) Feb 7 at 16:16
  • The files are named in this format: "2021/02/01 | 00_03_07.mp4" -- you mean there's a 2021 directory, with subdir 02, which contains a file named "01 | 00_03_07.mp4" ? filenames cannot contain a slash. Feb 7 at 18:14

Loop your files and find out last modification date, e.g. using date -r. Then create target directory and move the file there.

cd /path/to/mp4-files/
for f in *.mp4; do
    date=$(date +%F -r "$f")
    target="Security Videos $y/Security Videos $y-$m/Security Videos $y-$m-$d"
    mkdir -p "$target"
    mv "$f" "$target"

Mac version:

cd /path/to/mp4-files/
for f in *.mp4; do
    date=$(stat -f %Sm -t %Y-%m-%d "$f")
    target="Security Videos $y/Security Videos $y-$m/Security Videos $y-$m-$d"
    mkdir -p "$target"
    mv "$f" "$target"

With so many files, find | xargs is the pattern to use:

find . -type f -name \*.mp4 -print0 \
| xargs -0 bash -c '
    pattern="([0-9]{4})/([0-9]{2})/([0-9]{2}) [|] (.*)"
    for file; do
       [[ $file =~ $pattern ]] || continue
        dir="Security Videos $year-$mon-$day"
        mkdir -p "$dir"
        mv -v "$file" "$dir/${BASH_REMATCH[4]}"
' sh

The trailing "sh" is used by bash as $0, and the for file loop iterates over $1, $2, ...


The following will do most of what you request using 'ExifTool'. It can be downloaded from https://exiftool.org/ or installed with homebrew on your Mac: brew install exiftool. ExifTool reads the EXIF metadata "Exchangeable Image File Format" embedded in digital images and can use the information to rename files, create directories and move images there. There is extensive documentation and example usage at the website and in the man page.

Open a terminal and run the following in the directory where your mp4's reside:

exiftool -d %Y%m%d-%H%M%S.%%e '-Filename<'CreateDate' *mp4

This will rename the files to a form like 20191214-165635.mp4

Then execute

exiftool -r -d %Y/%m/%d '-directory<$CreateDate/%d' .

This will create a directory structure like: '2021/02/05/'

and put each mp4 in it's folder based on the date.

Note that the date used is that from the metadata embedded in the file, not the one shown by ls or MacOS Finder. If you have done any image processing or certain other file operations the latter date will reflect these operations rather than the creation date of the image. I would think having the correct creation date would be important for security video.

EXIF tags vary depending on the model of camera. Yours may have something like 'Date/Time Original' instead of 'Create Date'. If so, replace 'CreateDate' in the above commands with the corresponding tag from your camera without any spaces or backslashes. To view the EXIF data execute exiftool example_filename.mp4. This will dump all the EXIF tags. To view only those with dates, execute exiftool example_file.mp4 | grep -i date.

Processing a million files make take a long time depending on their size. The following script will select a random subset of 500 files and put them in subdirectory 'tmp'. Create it in the directory where your mp4's are, make it executable with chmod u+x select_files.sh and run it: ./select_files.sh. Move to the directory (cd tmp) and run the above exiftool commands to confirm that they do what you want.


# select_files.sh - Copy a random selection of files to subdirecotry 'tmp'

ext="mp4"                       # File extension
num=500                         # Number of files to select

ls *.${ext} | sort -R | head -n $num > random_files.txt

mkdir tmp

while read -r file ; do
    cp $file ./tmp
done < random_files.txt

# End

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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