#!/bin/env nu def main [] { } export def `main import` [ src: string # source path dst: string # destination path --exif-only # only take the exif date --link # replace the originals with symlinks --tag-origin # tag with origin folder name ] { print "Importing" if ("moved.csv" | path exists) == false { "source,destination\n" | save moved.csv } let entries = ( glob $"($src | str trim --right --char '/')/**/*" | each { try { ls -l $in } catch {|e| print_line -e $"Failed to get metadata of ($e)"; []} } | where { ($in | length) > 0 } | each { first } | where type == 'file' | where size > 0B ) let total_count = $entries | length print $"Copying ($total_count) entries" ( $entries | enumerate | par-each {|entry| let file = $entry.item print_line $file.name progress $entry.index $total_count let meta = exiftool -j $file.name | from json | get 0 mut date = $file.created? if $date == null { $date = $file.modified? } let path_parts = $file.name | path parse mut using_exif = false if $meta.DateTimeOriginal? != null { try { $date = (parse_exif_timestamp $meta.DateTimeOriginal $meta.OffsetTimeOriginal?) $using_exif = true } catch {|e| print_line -e $"Failed to parse datetime ($meta.DateTimeOriginal) ($e)" } } if $using_exif == false and $exif_only { let folder_rel = ( try { $path_parts.parent | path relative-to $src | into string } catch { $path_parts.parent | path parse | get stem }) let folder = $dst | path join "unknown" | path join $folder_rel mkdir $folder let file_name = $folder | path join $"($path_parts.stem).($path_parts.extension)" archive-cp $file.name $file_name --tag=$tag_origin print_line $"Inaccurate date for file ($file.name)" progress ($entry.index + 1) $total_count return; } let file_name = $"($date | format date '%Y-%m-%d_%H%M%S')_($path_parts.stem).($path_parts.extension)" print_line $"Filename: ($file_name)" progress $entry.index $total_count let folder_name = $dst | path join ($date | format date "%Y/%Y-%m-%B") print $"Destination folder: ($folder_name)" mkdir $folder_name archive-cp $file.name ($folder_name | path join $file_name) --link=$link --tag=$tag_origin print_line $"Copied ($meta.SourceFile)" progress ($entry.index + 1) $total_count }) } def parse_exif_timestamp [timestamp: string, offset?: any] { let components = $timestamp | split row " " let date = $components | first let time = $components | last $"($date | str replace -a ':' '.') ($time)($offset)" | into datetime } def archive-cp [src: string, dst: string, --link, --tag] { rsync -X -U -p -t -g -o -u --info=ALL $src $dst $"($src),($dst)\n" | save -a moved.csv if $tag { xattr -w user.xdg.tags ($src | path parse | get parent | path parse | get stem) $dst } if $link { rm $src ln -s $dst $src } } def progress [current: number, total: number] { let progress_perc = ($current / $total) * 100 print $"($current) / ($total) \(($progress_perc | math round -p 2)%\): (0..($progress_perc / 5 | math round) | each { '#' } | str join '')(ansi -e F)" } def print_line [...msg: any, -e] { print --stderr=$e $"(ansi -e 2K)( $msg | each { into string } | str join ' ' )" }