You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

112 lines
3.4 KiB
Plaintext

#!/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 ' ' )"
}