Retour au blog
août 2022·1 min de lectureTraduit par IA
Langue:DeutschEnglishFrançaisÖsterreichischKlingonian Version originale: Deutsch

Autosort : trier simplement et rapidement images et vidéos

#autosort#bash#dateien#dateien-sortieren#gopro#ordnerstruktur#shell#skript#sortieren

Ceci est le successeur du script présenté ici : GoPro & Photos : renommer et copier automatiquement

Comme je photographie et filme beaucoup, une structure de fichiers et de dossiers organisée est extrêmement importante pour moi. Je range toujours mes images et vidéos au format

{video_target|foto_target}/YYYY-MM-DD/YYYY-MM-DD-HH-MM-SS.ext

On le fait une ou deux fois. Puis cela devient répétitif, ennuyeux, et il faut une solution automatisée… surtout qu'on a vite pris > 1000 photos et que les déplacer et renommer à la main n'a vraiment rien d'amusant.

C'est ainsi qu'est née l'idée d'écrire un petit script shell qui trie et renomme automatiquement mes fichiers par date, en parcourant aussi les sous-dossiers.

Le script parcourt d'abord un ensemble de dossiers et leurs sous-dossiers à la recherche de fichiers d'un type de média prédéfini. Quand un fichier média est trouvé, le script détermine s'il s'agit d'une image ou d'une vidéo. Selon le cas, le fichier est copié dans le dossier cible correspondant, au même format que ci-dessus.

Si la copie réussit (= les valeurs MD5 de la source et de la cible concordent), l'original est supprimé.

Si le dossier cible est introuvable, le fichier n'est pas copié et est ignoré.

Les variables suivantes doivent être adaptées :

  • video_target : les vidéos sont copiées ici
  • foto_target : les photos sont copiées ici
  • sources : ce sont les dossiers dans lesquels on cherche automatiquement vidéos et photos. Il est aussi possible d'indiquer individuellement un chemin à chaque exécution.
  • video_extensions : les fichiers avec ces extensions sont reconnus comme vidéos
  • foto_extensions : les fichiers avec ces extensions sont reconnus comme photos

Voici le script, que l'on peut aussi télécharger directement :

Télécharger Shell_Copy_Rename_Media.zip

Amusez-vous bien.

#!/bin/sh

video_target="/Volumes/Videos/Videos"
foto_target="/Volumes/Extern01/Fotos"
sources=("/Volumes/Untitled/MP_ROOT" "/Volumes/GoPro/DCIM/100GOPRO" "/Volumes/Untitled/DCIM/100MSDCF" "/Volumes/Untitled/private/AVCHD/BDMV/STREAM")
video_extensions=("mp4" "mov" "flac" "webm" "mkv" "flv" "vob" "ogv" "ogg" "drc" "gif" "gifv" "mng" "avi" "mts" "m2ts" "ts" "mov" "qt" "wmv" "yuv" "rm" "rmvb" "viv" "asf" "amv" "mp4" "m4p" "m4v" "mpg" "mp2" "mpeg" "mpe" "mpv" "m2v" "m4v" "svi" "3gp" "3g2" "mxf" "roq" "nsv" "f4v" "f4p" "f4a" "f4b" "wav")
foto_extensions=("jpg" "heic" "arw" "raw" "crw" "jpeg")
total_errors=0

docopy()
{
  path=$1
  log INFO "Copy from path: '$path'"
  num_files=`ls -1q "$path" | wc -l`
  filecount=0
  err_count=0

  for file in $path/*; do
      filecount=$((filecount+1))
      log INFO "File/Folder #$filecount of $num_files"

      if [[ -d ${file} ]]; then
        log INFO "$file is Directory. Check it's subdirectories."
        docopy "$file"
      elif [ ! -f "$file" ]; then
          log INFO "$file does not contain any files. Next."
          continue
      fi

      original_file_datetime=`stat -f "%Sm" -t "%Y-%m-%d-%H-%M-%S" "$file"`
      original_file_name=$(basename ${file})
      original_file_extension="${original_file_name##*.}"

      GetPathByExtension "$original_file_extension"

      if [ "$filetype_path" = "UNKNOWN" ]; then
        log ERR "$original_file_extension is not a valid format. Continue with next file"
        continue
      elif [ ! -d "$filetype_path" ]; then
        log ERR "Target path '$filetype_path' unavailable"
        err_count=$((err_count+1))
        continue
      fi

      target_folder_name=`stat -f "%Sm" -t "%Y-%m-%d" "$file"`
      target_path="$filetype_path/${target_folder_name}"
      target_file="$target_path/$original_file_name"

      log INFO "Source: ${file}"
      log INFO "Destination: ${target_path}"
      log INFO "Copying..."
      
      if [ -f "$file" ] && [ -f "$target_path" ]; then
        md5SrcFile=$(md5 -q "$file")
        md5DstFile=$(md5 -q "$target_file")
        if [ "$md5SrcFile" == "$md5DstFile" ]; then
          log WARN "The file ${target_path} already exists with MD5 Matching. Skip?"
          read -p "Y to Skip, C to Continue " skip
          if [ "$skip" == "Y" ]; then
            continue
          fi
        fi 
      fi

      mkdir -p "${target_path}"
      md5SrcFile=$(md5 -q "$file")
      rsync -ct ${file} ${target_path}
      md5DstFile=$(md5 -q "$target_file")

      if [ "$md5SrcFile" == "$md5DstFile" ] && [ "$md5SrcFile" != "" ] && [ "$md5DstFile" != "" ];
      then
        rm ${file}
      else
        log INFO "ERROR: MD5 MISMATCH"
        exit
      fi

      renamed_file="$target_path/$original_file_datetime.$original_file_extension"
      incrementor=0
      while [ -f "$renamed_file" ]; do
        incrementor=$((incrementor+1))
        renamed_file="$target_path/$original_file_datetime.$incrementor.$original_file_extension"
      done

        mv $target_file $renamed_file

      log IFNO "File Done"
    done

    log INFO "Finished with $err_count errors"
}

GetPathByExtension()
{
  extension=`echo "$1" | dd  conv=lcase 2> /dev/null`
  if [[ " ${video_extensions[*]} " =~ " ${extension} " ]]; then
    filetype_path="$video_target"  
  elif [[ " ${foto_extensions[*]} " =~ " ${extension} " ]]; then
    filetype_path="$foto_target"  
  else
    filetype_path="UNKNOWN"
  fi
}

log()
{
  [ "$1" = "ERR" ] && echo "\033[0;31m$2\033[0m" && err_count=$((err_count+1)) && total_errors=$((total_errors+1))
  [ "$1" = "WARN" ] && echo "\033[0;31m$2\033[0m"
  [ "$1" = "SUCCESS" ] && echo "\033[0;32m$2\033[0m"
  [ "$1" = "INFO" ] && echo "$2"
}

scandefault()
{
  log INFO "Scanning default folders."
  for i in "${sources[@]}"; do
    if [ -d "$i" ]; then
      docopy "$i"
    fi
  done
}

scanindividual()
{
  read -p "Do you want to copy files from an individual path? Press Y or N: " tmp

  if [ "$tmp" = "Y" ]; then
    read -p "Enter Source path: " src
    if [ -d "$src" ]; then
      docopy "$src"
    else
      log ERR "Path $src does not exist. Aborted."
      total_errors=$((total_errors+1))
    fi
  fi
}

scandefault
scanindividual

hasErrors=$false
[ "$total_errors" -gt 0 ] && hasErrors=$true || hasErrors=$false
if [[ $hasErrors -eq $true ]]; then
  log ERR "==========================\r\nFinished with errors\r\nTotal Errors: $total_errors\r\n=========================="
else
  log SUCCESS "==========================\r\nFinished without errors\r\n=========================="
fi
Plus récentFirmware Marlin pour SKR Mini E3 V3Plus ancienPromises