Chucrute
Chucrute

Reputation: 41

Shell script to move photos into folders with date YYYYMMDD

I have an IP camera that sends a photo every minute to a folder on a PC (Linux) with (mv *20150501* 20150501).

Where the camera sends the following filename:

Schedule_20150501-103642.jpg

I would like to make a shell script that:

mencoder "mf://*.jpg" -mf fps=12:type=jpg -ovc lavc -lavcopts vcodec=mpeg4:mbd=2:trell:vbitrate=7000 -oac copy -o Zeitraffer`**20150501**.mp4

Base folder is: snap

Sub folder: snap/(date +%YYYY%mm%dd)

Until now, I do all that manually and separately using mv. Then I move into the folders and modify the script for the time lapse. :-(

Until now, I have a script to make at least a bulk of folders by date:

#!/bin/bash

read -p "Geben Sie den ersten Ordner an (JJJJMMTT): " now  
read -p "Geben Sie den letzten Ordner an (JJJJMMTT): " end  

while [ "$now" != "$end" ] ;
do
now=`date +"%Y%m%d" -d "$now +1 day"`;
mkdir $now
done 

Any idea?

Upvotes: 3

Views: 2942

Answers (4)

Matthias Braun
Matthias Braun

Reputation: 34353

Here's a solution I use to sort images and videos by their creation date, based on ExifTool:

#!/bin/bash

# Based on Exif metadata, gets the date and time a file was created
get_date_and_time() {

  local result;

  result=$(exiftool -binary -DateTimeOriginal "$1")

  # If the file metadata doesn't contain DateTimeOriginal try with another tag
  if [ -z "$result" ]; then
    result=$(exiftool -binary -CreateDate "$1")
  fi

  # https://www.shellcheck.net/wiki/SC2059
  printf "%s" "$result"
}

main() {

  # When the script's called without arguments, sort
  # files found in the current directory
  if (( $# != 1 )); then
    dir_with_files="."
  # Otherwise, use the first argument as the directory
  else
    dir_with_files="$1"
  fi

  echo "moving files in \"$dir_with_files\""

  for f in "$dir_with_files"/*
  do
    if [ -f "$f" ]; then
      date_time=$(get_date_and_time "$f")
      if [ -n "$date_time" ]; then
        # Remove the time and keep the date by removing
        # everything after the first space
        date="${date_time%% *}"

        # Replace all colons with dashes in the date
        dir_name="${date//:/-}"
        # Create the directory if it doesn't exist yet
        if [ ! -d "$dir_with_files/$dir_name" ]; then
          mkdir --verbose "$dir_with_files/$dir_name"
        fi

        mv --no-clobber --verbose "$f" "$dir_with_files/$dir_name"

      else
        echo "No date for $f"
      fi
    fi
  done

}

main "$@"

If you put that code in sort_by_day.sh and make it executable with chmod +x sort_by_day.sh, you can call it like this:

  • ./sort_by_day.sh to sort files in the current directory.
  • ./sort_by_day.sh my_images to sort files in the directory my_images.

Based on the Exif tags DateTimeOriginal or —if the file doesn't have that tag— CreateDate, the script will create directories like 2023-05-23 and move files that were created on that day into the corresponding directory.

If a file doesn't have those Exif tags, the script does not move it.

I have used this to sort JPGs and MOVs.

Upvotes: 1

Chucrute
Chucrute

Reputation: 41

First of all, Thanks to every comment of you!!! REGEX is toooo difficult for me. Thanks alyway. After a lot of research today I fit together a lot of puzzle parts. What I got is this: The only thing is that if there is already a folder the respective files are not copied due to the while function. But as the script stops one day before today this should not be a problem. Then I made two more scripts for the case in the past I forgot to make a movie it will be created. The other checks if the MP4 file already exists in the plex folder and if not copy the file there. Actually I just modified the script for that.

The script for "normal" work:

#!/bin/bash
read -p "Geben Sie den ersten Ordner an (JJJJMMTT): " begin  
end=$(date +%Y%m%d -d "-1 day")                                       
 while [ $begin != $end ] 
do
begin=`date +"%Y%m%d" -d "$begin +1 day"`
if [ ! -d $begin ]  # Prüfen, ob es den Ordner gibt.                                      
then
    /bin/mkdir $begin 
    echo "Ordner $begin erstellt"
    mv *$begin*.jpg $begin  
echo "Bilder vom $begin verschoben nach $begin"
 cd $begin  
 $(mencoder mf://*.jpg -mf fps=12:type=jpg -ovc lavc -lavcopts vcodec=mpeg4:mbd=2:trell:vbitrate=7000 -oac copy -o Zeitraffer$begin.mp4)
  cp Zeitraffer$begin.mp4 /Plexfolder/ 
 echo "Kopiere Zeitraffer$begin.mp4 nach /RAID5/filme/Kamera/"
 cd ..
 fi
 done 

The script to check if the MP4 file exists if not creates it and copies to the plex folder:

#!/bin/bash

  read -p "Geben Sie den ersten Ordner an (JJJJMMTT): " begin  
  end=$(date +%Y%m%d -d "-1 day")       
  while [ $begin != $end ] 
  do
  begin=`date +"%Y%m%d" -d "$begin +1 day"`
  if [ -d $begin ] 
  then
  cd $begin 
  if [ ! -f Zeitraffer$begin.mp4 ] #Prüfen, ob es eine MP4 Datei gibt 
  then
  $(mencoder mf://*.jpg -mf fps=12:type=jpg -ovc lavc -lavcopts vcodec=mpeg4:mbd=2:trell:vbitrate=7000 -oac copy -o Zeitraffer$begin.mp4)
  cp Zeitraffer$begin.mp4 /plexfolder/ 
  echo "Kopiere Zeitraffer$begin.mp4 nach /plexfolder/"
  fi  
  cd ..
  fi
  done 

And the one to copy the missing MP4 file to the plex folder:

#!/bin/bash
read -p "Geben Sie den ersten Ordner an (JJJJMMTT): " begin  
end=$(date +%Y%m%d -d "-1 day") 
while [ $begin != $end ] 
do
begin=`date +"%Y%m%d" -d "$begin +1 day"`
if [ -d $begin ]          
then
cd $begin 
if [ ! -f "/plexfolder/Zeitraffer$begin.mp4" ] 
then
cp Zeitraffer$begin.mp4 /RAID5/filme/Kamera/
echo "Kopiere Zeitraffer$begin.mp4 nach /RAID5/filme/Kamera/"
fi  
cd ..
fi
done 

And you know what's the best??? IT REALLY WORKS!!! I cannot believe that I did it!!!

Thanks a lot for your help!!!

Upvotes: 1

Slizzered
Slizzered

Reputation: 899

This solution will autoselect the first date and move all images together and process them afterwards with mencoder. The solution has several assumtions that should be easy to achieve:

  • if a folder exists, it is complete (filled with all pictures and contains the video)
  • if the folder is complete, no more images for this folder are left in the base folder
  • all images in the base folder have not been processed (no other pictures of the same day have been processed)
  • today's folder should not be touched, since it might still be incomplete (not all pictures done)

Based on these assumptions, the solution is pretty efficient, since it moves all pictures of a single day at the same time. I included 2 methods to search for the earliest day to start. If you produce a LOT of files each day, it might be faster to look at the directories. If you have directories for many years (so, tens of thousands of directories), it might be faster to look at the remaining images instead.

today=$(date +"%Y%m%d" -d "now")

#first day to process based on existing images
day=$(ls Schedule_* | grep -o "[[:digit:]]\{8\}" | uniq | sort | tail -n1)

# first day to process based on existing folders (might be faster)
#day=$(find . -type d -regex "./[0-9]+" -printf '%P\n' | sort | tail -n1)

# initial increment of day
day=$(date +"%Y%m%d" -d "$day +1 day")

while [ $day -lt $today ] ; do
  mkdir $day
  mv Schedule_${day}-*.jpg ${day}/. 2>/dev/null
  cd $day
    # run mencoder
  cd ..
  day=$(date +"%Y%m%d" -d "$day +1 day")
done

Upvotes: 0

Jakub Pasoń
Jakub Pasoń

Reputation: 231

Here is a sample that can help you:

shopt -s nullglob

for f in Schedule*.jpg
do
    dir_date=`echo "$f"|sed -e 's/Schedule_\([0-9]\{8\}\)-.*/\1/'`
    mkdir -p "$dir_date"
    mv "$f" "$dir_date"
done

for d in 20*
do
    if [[ -d "$d" ]]
    then
        cd "$d"
        if [[ ! -f Zeitraffer"$d".mp4 ]]
        then
            # Run mencoder here 
        fi
        cd ..
    fi
done

Nullglob is used, so if no files match, for will not take Schedule*.jpg pattern literally. Then extract date part with sed. Adding -p to mkdir makes sure that it doesn't print error if the directory already exists, so there is no need to check for it separately.

Upvotes: 0

Related Questions