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
112 lines
3.4 KiB
Plaintext
9 months ago
|
#!/bin/env nu
|
||
|
|
||
9 months ago
|
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 ' ' )"
|
||
|
}
|