Compare commits

..

22 Commits

Author SHA1 Message Date
Vincent Riquer
7944dbffe8 fix quoting issue 2026-01-16 03:45:34 +01:00
Vincent Riquer
6275485da6 v1.0.5 changelog 2026-01-16 03:45:34 +01:00
ScriptFanix
586785d546 Resolve "Store dest filename relative" 2026-01-16 03:45:34 +01:00
Vincent Riquer
0b08622108 Update CHANGELOG 2026-01-16 03:45:34 +01:00
ScriptFanix
8a53f8b07a Resolve "Script is uselessly verbose" 2026-01-16 03:45:34 +01:00
ScriptFanix
ff2d93feda Revert "Merge branch '27-script-is-uselessly-verbose' into 'dev'"
This reverts merge request !34
2026-01-16 03:45:34 +01:00
ScriptFanix
a60e12a2da Resolve "Many error codes are not defined" 2026-01-16 03:45:34 +01:00
ScriptFanix
cf981eee25 Resolve "Script is uselessly verbose" 2026-01-16 03:45:34 +01:00
Vincent Riquer
301f51f2dd allow ignoring microseconds in file timestamps 2026-01-16 03:43:54 +01:00
ScriptFanix
9acb957cb8 Resolve "Store dest filename relative" 2026-01-16 03:43:54 +01:00
Vincent Riquer
094ef5f68f quickfix: createindex: gracefully handle empty channel count, sampling rate, bitdepth 2026-01-16 03:43:54 +01:00
Vincent Riquer
803983a5a6 Hotfix: createindex: fix ID3v1 genre index path 2026-01-16 03:43:54 +01:00
Vincent Riquer
73f00a1fac Hotfix: missing quote in createindex 2026-01-16 03:43:54 +01:00
Vincent Riquer
66d67dbd3d Hotfix: commit more often when reading tags 2026-01-16 03:43:54 +01:00
ScriptFanix
fbabf840de Resolve "ffmpeg tags are always NULL" 2026-01-16 03:43:54 +01:00
Vincent Riquer
a7f6668e72 quickfix: replace calls to date with builtin printf or $EPOCHSECONDS 2026-01-16 03:43:54 +01:00
Vincent Riquer
4e2bb8aab9 README: update test collection 2025-05-02 03:19:44 +02:00
ScriptFanix
e960b18462 getInfos::guess skeleton 2025-04-30 02:53:48 +02:00
Vincent Riquer
7ff9923113 Setup 2025-04-30 02:46:15 +02:00
Vincent Riquer
a0cb1bae1b Switch to an array 2025-04-30 02:46:15 +02:00
Vincent Riquer
1a75cd4764 documentation 2025-04-30 02:46:15 +02:00
Vincent Riquer
298f6f1c60 Tag guessing config 2025-04-30 02:46:15 +02:00
35 changed files with 239 additions and 118 deletions

View File

@ -1,12 +1,3 @@
# 1.0.6
### BUGS
* Support for newline character in filenames
* Fix obsolete files deletion
### BUGS (Minor)
* Fix timing information
* Fix level 3+ debug levels (hanging waiting for child processes)
# 1.0.5
### BUGS (Minor)
* `toys/createindex`: handle empty channel count, bitdepth and sampling rate cleanly

View File

@ -20,19 +20,19 @@ in the same format, it will want a constant sample-rate and bitrate. You can
have AtOM do that!
Here's what I have for my tests:
| Directory | Format | Sample rate | Bitrate | Channels | FAT32 compat. | ASCII | Size |
| --------- | ------ | ----------- | --------- | -------- | ------------- | ----- | ---- |
| 0-Full | Mixed | Mixed | Mixed | Mixed | No | No | 568G |
| 1-High | Vorbis | Same | Quality 5 | Same | Yes | No | 143G |
| 2-Medium | Opus | Same | 64 | Same | Yes | No | 60G |
| 3-Small | Opus | Same | 32 | Same | Yes | No | 31G |
| 4-MP3 | MP3 | 44100 | 128 | 2 | Yes | Yes | 119G |
| Directory | Format | Sample rate | Bitrate | Channels | Normalize | FAT32 compat. | ASCII | Size |
| --------- | ------ | ----------- | --------- | -------- | --------- | ------------- | ----- | ---- |
| 0-Full | Mixed | Mixed | Mixed | Mixed | No | No | No | 508G |
| 1-High | Vorbis | Original | Quality 5 | Same | No | Yes | No | 136G |
| 2-Medium | Opus | Original | 64 | Same | No | Yes | No | 58G |
| 3-Small | Opus | Original | 32 | Same | No | Yes | No | 30G |
| 4-MP3 | MP3 | 44100 | 128 | 2 | No | Yes | Yes | 113G |
* URL: https://framagit.org/atom/AtOM/
* Author: Vincent Riquer <vincent+prog.atom@riquer.fr>
* Copyright/left: 2012-2013,2015,2025-2026 Vincent Riquer - GPLv3
* Copyright/left: 2012-2013,2015,2025 Vincent Riquer - GPLv3
## Dependencies
### Required:

45
atom
View File

@ -202,7 +202,7 @@ echo '
FROM destination_files
WHERE source_file_id is NULL;' >&3
read -u4 -r -d $'\0' removecount
read -u4 removecount
until (( ${#removefile[@]} == removecount ))
do
echo '
@ -219,15 +219,15 @@ do
SELECT "AtOM:NoMoreFiles";
' >&3
read -u4 -r -d $'\0' line
read -u4 line
until [[ $line == AtOM:NoMoreFiles ]]
do
removeFileId=${line%%::AtOM:SQL:Sep::*}
rest=${line#*::AtOM:SQL:Sep::}
removeFileDestName=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
removeFileDestName=${line%%::AtOM:SQL:Sep::*}
rest=${line#*::AtOM:SQL:Sep::}
removefile[$removeFileId]="${destinationpath["$removeFileDestName"]}/${rest%%::AtOM:SQL:Sep::*}"
read -u4 -r -d $'\0' line
read -u4 line
done
done
@ -239,7 +239,7 @@ do
filename=${removefile[id]}
if [ -n "$filename" ]
then
if rm "$filename"
if rm -f "$filename"
then
Delete destination_files <<<"id = $id"
(( ++deleted ))
@ -387,7 +387,7 @@ echo '
<> CAST(source_files.last_change AS TEXT)
AND mime_type_actions.destination_id = destinations.id
AND mime_type_actions.action = 1;' >&3
read -u4 -r -d $'\0' filecount
read -u4 filecount
if [ -n "$maxbatch" ] && (( maxbatch < filecount ))
then
(( togo = filecount - maxbatch ))
@ -436,11 +436,11 @@ echo '
(( maxbatch )) && echo "LIMIT $maxbatch" >&3
echo ';
SELECT "AtOM:NoMoreFiles";' >&3
read -u4 -r -d $'\0' line
read -u4 line
while ! [[ $line = AtOM:NoMoreFiles ]]
do
decodefiles+=("$line::AtOM:SQL:Sep::")
read -u4 -r -d $'\0' line
read -u4 line
done
(( cron )) || echo -n $'Creating tasks...\033[K'
@ -550,9 +550,9 @@ done
echo 'COMMIT;' >&3
(( cron )) || echo -n $'\r\033[K'
(( count )) \
&& echo "Created $count tasks for $filecount files" \
"${togo:+($togo left) }" \
"${copies:+($copies immediate copies)}"
&& echo "Created $count tasks for $filecount files \
${togo:+($togo left) } \
${copies:+($copies immediate copies)}"
# remove perl unicode to ascii coprocess
(( textunidecodeneeded )) && eval exec "${toascii[1]}>&-"
@ -675,17 +675,20 @@ endtime=$EPOCHSECONDS
elapsedseconds
/
( 24*60*60 )
)) || unset days
)) || true
(( days )) || unset days
(( hours =
( elapsedseconds - ( days*24*60*60 ) )
/
( 60*60 )
)) || (( days )) || unset hours
)) || true
(( days && hours )) || unset hours
(( minutes =
( elapsedseconds - ( ( days*24 + hours ) *60*60 ) )
/
60
)) || (( days || hours )) || unset minutes
)) || true
(( days && hours && minutes )) || unset minutes
(( seconds =
elapsedseconds
-
@ -773,11 +776,11 @@ then
WHERE tasks.status = 2;
SELECT "AtOM:NoMoreFiles";' >&3
read -u4 -r -d $'\0' line
read -u4 line
while ! [[ $line = AtOM:NoMoreFiles ]]
do
failedtasks+=("$line")
read -u4 -r -d $'\0' line
read -u4 line
done
for line in "${failedtasks[@]}"
do
@ -833,11 +836,11 @@ do
SELECT "AtOM:NoMoreFiles";
' >&3
read -u4 -r -d $'\0' line
read -u4 line
while [[ $line != AtOM:NoMoreFiles ]]
do
renamefiles+=("$line")
read -u4 -r -d $'\0' line
read -u4 line
done
if (( ${#renamefiles[@]} ))
then
@ -940,11 +943,11 @@ echo '
(( cron )) || echo -n 'Removing obsolete files...'$'\033[K'
lines=()
read -u4 -r -d $'\0' line
read -u4 line
while [[ $line != AtOM:NoMoreFiles ]]
do
lines+=("$line")
read -u4 -r -d $'\0' line
read -u4 line
done
echo 'BEGIN TRANSACTION;' >&3
for line in "${lines[@]}"

View File

@ -52,6 +52,20 @@ Sections:
Default: /var/lib/mpd/music
* skip <directory>: String. Files in <directory> will be ignored. Note that
<directory> can be any expression accepted by find.
* tag-guessing <expression>: String. Filenaming scheme to allow for guessing
tags from filenames and directories. The placeholders are the same as thosefor rename below:
%{album},
%{albumartist},
%{artist},
%{disc},
%{genre},
%{releasecountry},
%{title},
%{track},
%{year}.
* tag-guessing-trigger <tag>: String. Specify multiple times for multiple
tags.
If <tag> cannot be fetched by tag readers, guessing will be attempted.
[<some arbitrary string>]
Each section not named 'general' or 'source' will define a new destination.

View File

@ -52,6 +52,33 @@ skip /last
skip /lastfm
skip /zzz-atrier
# Tag guessing expresssion. Uses same values as "rename" below. This is used to
# guess tags from filenames and paths. This is useful for files with no tags but
# can lead to issues if a strict naming scheme is not used.
# Tag guessing disabled if unset (default).
# %{album},
# %{albumartist},
# %{artist},
# %{disc} (1 digit),
# %{genre},
# %{releasecountry} (2 letter code),
# %{title},
# %{track} (2 digits),
# %{year}.
#tag-guessing %{genre}/%{albumartist}/%{year}-%{album}-%{releasecountry}/%{disc}%{track}--%{artist}-%{title}
# Guess tags on missing infos:
#tag-guessing-trigger artist
#tag-guessing-trigger albumartist
#tag-guessing-trigger album
#tag-guessing-trigger releasecountry
#tag-guessing-trigger disc
#tag-guessing-trigger title
#tag-guessing-trigger track
#tag-guessing-trigger year
#tag-guessing-trigger genre
[Vorbis]
# Each section not named 'general' or 'source' will define a new destination.

View File

@ -7,5 +7,11 @@ getConfigSource() {
'skip')
skippeddirectories+=( "$value" )
;;
'tag-guessing')
tagguessing="$value"
;;
'tag-guessing-trigger')
tagguessingtriggers+=( "$value" )
;;
esac
}

View File

@ -21,6 +21,16 @@ printConfig() {
printed=1
done
unset printed
echo " |Tag guessing expression|$tagguessing"
for trigger in "${tagguessingtriggers[@]}"
do
(( printed )) \
&& echo -n ' | |' \
|| echo -n ' |Tag guessing triggers|'
echo "$trigger"
printed=1
done
for destination in ${destinations[@]}
do
cat <<-EOF

View File

@ -54,6 +54,32 @@ path $sourcepath
cat <<-EOCfg
# Tag guessing expresssion. Uses same values as "rename" below. This is used to
# guess tags from filenames and paths. This is useful for files with no tags but
# can lead to issues if a strict naming scheme is not used.
# Tag guessing disabled if unset (default).
# %{album},
# %{albumartist},
# %{artist},
# %{disc} (1 digit),
# %{genre},
# %{releasecountry} (2 letter code),
# %{title},
# %{track} (2 digits),
# %{year}.
#tag-guessing %{genre}/%{albumartist}/%{year}-%{album}-%{releasecountry}/%{disc}%{track}--%{artist}-%{title}
tag-guessing $tagguessing
# Guess tags on missing infos:
#tag-guessing-trigger artist
#tag-guessing-trigger albumartist
EOCfg
for trigger in "${tagguessingtriggers[@]}"
do
echo $'tag-guessing-trigger\t'"$trigger"
done
EOCfg
for destination in "${destinations[@]}"
do

View File

@ -22,11 +22,11 @@ copyFiles_action() {
AND mime_type_actions.action = 2;
SELECT "AtOM:NoMoreFiles";' >&3
read -u4 -r -d $'\0' line
read -u4 line
while ! [[ $line = AtOM:NoMoreFiles ]]
do
copyfiles+=("$line")
read -u4 -r -d $'\0' line
read -u4 line
done
echo 'BEGIN TRANSACTION;' >&3
@ -91,10 +91,9 @@ copyFiles_action() {
"$sourcepath/$sourcefilename" \
"$destdir"
then
destfilename=${sourcefilename//$'\n'/::AtOM:NewLine:SQL:Inline::}
Update destination_files \
filename \
"$destdir/${destfilename##*/}"\
"$destdir/${sourcefilename##*/}"\
rename_pattern \
"${destinationrenamepath[$destination]}/${destinationrename[$destination]}"\
fat32compat \

View File

@ -21,7 +21,7 @@ guessPath() {
LIMIT 1
),"0.0");
'>&3
read -u4 -r -d $'\0' timestamp
read -u4 timestamp
if (( ${timestamp/./} == 0 ))
then
return 2
@ -46,7 +46,7 @@ guessPath() {
LIMIT 1
),"AtOM:NotFound");
'>&3
read -u4 -r -d $'\0' filename
read -u4 filename
if [[ $filename != AtOM:NotFound ]]
then
echo "${filename%/*}"

View File

@ -26,7 +26,6 @@ Insert() {
insert_values+=$value
;;
*)
value=${value//::AtOM:NewLine:SQL:Inline::/$'\n'}
insert_values+='"'"${value//\"/\"\"}"'"'
;;
esac
@ -37,7 +36,7 @@ Insert() {
"( $insert_values );" >&3
(( no_id )) || {
echo 'SELECT LAST_INSERT_ROWID();' >&3
read -u4 -r -d $'\0' results
read -u 4 results
echo "$results"
}
}

View File

@ -19,7 +19,6 @@ Select() {
while read key operator value
do
(( ${#where_statement} )) && where_statement+=( "AND" )
value=${value//::AtOM:NewLine:SQL:Inline::/$'\n'}
where_statement+=( "$key $operator "'"'"${value//\"/\"\"}"'"' )
done
echo "SELECT IFNULL(" \
@ -27,7 +26,7 @@ Select() {
"WHERE ${where_statement[@]})" \
",'SQL::Select:not found'" \
");" >&3
read -u 4 -r -d $'\0' results
read -u 4 results
if ! [[ $results == "SQL::Select:not found" ]]
then
echo "$results"

View File

@ -1,5 +1,5 @@
#!/usr/bin/env bash
currentdbversion=8
currentdbversion=7
checkDatabaseVersion() {
local dbversion
if dbversion=$(Select atom version <<<"\"1\" = 1")
@ -15,9 +15,9 @@ checkDatabaseVersion() {
dbversion=$(Select atom version <<<"\"1\" = 1")
done
else
echo "Database schema version $dbversion is" \
"higher thanthat of this version of" \
"AtOM ($currentdbversion). Bailing out." >&2
echo "Database schema version $dbversion is higher than
that of this version of AtOM
($currentdbversion). Bailing out." >&2
exit $EDBVERSION
fi
else

View File

@ -3,8 +3,7 @@ closeDatabase() {
echo 'vacuum;' >&3
echo .quit >&3
(( debug )) && echo -n "Waiting for SQLite to terminate... "
(( debug > 2 )) && exec 5>&-
wait $db_pid
wait
(( debug )) && echo OK
exec 3>&-
exec 4<&-

View File

@ -1,22 +1,14 @@
#!/usr/bin/env bash
openDatabase() {
local \
populate_db
[[ -f "$database" ]] || populate_db=1
rm -f "$tempdir"/sqlite.{in,out}
mkfifo "$tempdir"/sqlite.{in,out}
stdbuf -o0 sqlite3 -bail \
-newline $'::AtOM:SQL:EOL::\n' \
"$database" \
< "$tempdir/sqlite.in" \
| stdbuf -o0 \
sed 's/::AtOM:SQL:EOL::/\x0/g;s/\(\x0\)\xA/\1/g' \
sqlite3 -bail "$database" \
< "$tempdir/sqlite.in" \
> "$tempdir/sqlite.out" &
db_pid=$!
exec 3> "$tempdir"/sqlite.in
exec 4< "$tempdir"/sqlite.out
rm "$tempdir"/sqlite.{in,out}
rm "$tempdir"/sqlite.in "$tempdir"/sqlite.out
if (( debug > 2 ))
then
exec 5>&3
@ -28,7 +20,7 @@ openDatabase() {
echo 'PRAGMA recursive_triggers = ON;' >&3
echo 'PRAGMA temp_store = 2;' >&3
echo 'PRAGMA locking_mode = EXCLUSIVE;' >&3
read -u4 -r -d $'\0'
read -u4
unset REPLY
checkDatabaseVersion
}

View File

@ -18,11 +18,11 @@ FROM destination_files;
SELECT "AtOM::NoMoreData";' >&3
read -u4 -r -d $'\0' data
read -u4 data
while [[ $data != AtOM::NoMoreData ]]
do
datas+=( "$data" )
read -u4 -r -d $'\0' data
read -u4 data
done
echo 'BEGIN TRANSACTION;' >&3
for data in "${datas[@]}"

View File

@ -1,9 +0,0 @@
#!/usr/bin/env bash
upgradedatabase_7_8() {
echo "Upgrading database to version 8... (backup is $database.bak_v7)"
cp "$database" "$database.bak_v7"
echo 'Deletion of old files was failing. Users of previous versions (YOU!) are strongly advised to run cleandestinations with the "-r" flag.'
read -p "Press Enter to continue..."
Update atom version 8 <<<"1 = 1"
}

View File

@ -2,5 +2,5 @@
decodeMpcdec() {
tmpfile="${fileid}mpcdec"
commandline=(${ionice}mpcdec)
commandline+=("$sourcepath/${filename//$'\n'/::AtOM:NewLine:SQL:Inline::}" "$tempdir/$tmpfile.wav")
commandline+=("$sourcepath/$filename" "$tempdir/$tmpfile.wav")
}

View File

@ -2,5 +2,5 @@
decodeOpusdec() {
tmpfile="${fileid}opusdec"
commandline=(${ionice}opusdec)
commandline+=("$sourcepath/${filename//$'\n'/::AtOM:NewLine:SQL:Inline::}" "$tempdir/$tmpfile.wav")
commandline+=("$sourcepath/$filename" "$tempdir/$tmpfile.wav")
}

View File

@ -12,7 +12,7 @@ decodeSox() {
then
commandline+=("$1")
else
commandline+=("$sourcepath/${filename//$'\n'/::AtOM:NewLine:SQL:Inline::}")
commandline+=("$sourcepath/$filename")
fi
if [ -n "${destinationfrequency["$destination"]}" ] \
&& (( ${rate:-0} != ${destinationfrequency["$destination"]} ))

View File

@ -88,7 +88,6 @@ getDestDir() {
while [[ $part =~ / ]]
do
thispart="${part%%/*}"
thispart=${thispart//$'\n'/::AtOM:NewLine:SQL:Inline::}
if (( ${destinationascii["$destination"]} ))
then
echo "$thispart" >&${toascii[1]}
@ -101,7 +100,7 @@ getDestDir() {
fi
if ! [ -d "${destinationpath[$destination]}/$destdir" ]
then
mkdir -p "${destinationpath[$destination]}/${destdir//::AtOM:NewLine:SQL:Inline::/$'\n'}"
mkdir -p "${destinationpath[$destination]}/$destdir"
fi
destdir="${destdir//+(\/)//}"
}

View File

@ -55,11 +55,10 @@ getDestFile() {
destfile="${filename##*/}"
destfile="${destfile%.*}"
fi
destfile=$(sanitizeFile "$destfile")
destfile=${destfile//$'\n'/::AtOM:NewLine:SQL:Inline::}
if (( ${destinationascii["$destination"]} ))
then
echo "$destfile" >&${toascii[1]}
read -r -u${toascii[0]} destfile
fi
destfile=$(sanitizeFile "$destfile")
}

View File

@ -8,7 +8,7 @@ getFiles() {
(( cron )) || echo -n "Scanning $sourcepath... "
# We probably have thousands of files, don't waste time on disk writes
echo 'BEGIN TRANSACTION;' >&3
while read -d $'\0' time size filename
while read time size filename
do
if (( skip_us_timestamp ))
then
@ -17,7 +17,7 @@ getFiles() {
compare_time=$time
fi
if ! Select source_files id >/dev/null <<-EOWhere
filename = ${filename//$'\n'/::AtOM:NewLine:SQL:Inline::}
filename = $filename
mime_type > 0
last_change LIKE $compare_time
size = $size
@ -47,7 +47,7 @@ getFiles() {
mime_type $mimetypeid \
>/dev/null \
<<-EOWhere
filename ${filename//$'\n'/::AtOM:NewLine:SQL:Inline::}
filename $filename
EOWhere
(( ++new ))
if (( new % 1000 == 0 ))
@ -58,12 +58,12 @@ getFiles() {
fi
else
Update source_files last_seen $scantime <<-EOWhere
filename = ${filename//$'\n'/::AtOM:NewLine:SQL:Inline::}
filename = $filename
EOWhere
fi
progressSpin
done < <(
find "$sourcepath" "${prunes[@]}" -type f -not -name '.*' -printf "%T@ %s %P\0"
find "$sourcepath" "${prunes[@]}" -type f -not -name '.*' -printf "%T@ %s %P\n"
)
echo 'COMMIT;' >&3
(( cron )) || echo -n $'\r'

View File

@ -55,4 +55,58 @@ setupSource() {
done
unset count
cd - >/dev/null
cat <<-EODesc
Tag guessing pattern:
This is a pattern that will be used to guess the tag names of files
that do not have any tags. The pattern is a string with the following
variables:
%{album} - The album name
%{albumartist} - The album artist name
%{artist} - The artist name
%{disc} - The disc number - 1 digit
%{genre} - The genre name
%{releasecountry} - The country of the release - 2 letter code
%{title} - The title of the track
%{track} - The track number - 2 digits
%{year} - The year or date of the album
EODesc
read \
-e \
-i"${tagguessing} \
-p'Pattern: ' \
tagguessing
cat <<-EODesc
Tag guessing trigger(s):
Tags whose absence will trigger tag guessing.
album - The album name
albumartist - The album artist name
artist - The artist name
disc - The disc number
genre - The genre name
releasecountry - The country of the release
title - The title of the track
track - The track number
year - The year or date of the album
EODesc
count=${#tagguessingtriggers[@]}
for (( i=0 ; 1 ; i++ ))
do
read \
-e \
${tagguessingtriggers[i]+-i"${tagguessingtriggers[i]}"}\
-p'Tag guessing trigger: ' \
value
if [ -n "$value" ]
then
tagguessingtriggers[i]="$value"
elif (( i < count ))
then
unset tagguessingtriggers[i]
else
break
fi
done
unset count
}

10
lib/tags/getInfos::guess Normal file
View File

@ -0,0 +1,10 @@
#!/usr/bin/env bash
getInfosGuess_version='guess-1'
tagreaders+=( "$getInfosGuess_version" )
getInfos::Guess() {
tagreader="$getInfosGuess_version"
local \
infos \
: #FIXME
}

View File

@ -52,12 +52,12 @@ echo '
;
SELECT "AtOM:NoMoreFiles";' >&3
read -u4 -r -d $'\0' line
read -u4 line
while ! [[ $line = AtOM:NoMoreFiles ]]
do
tagfiles+=("$line")
(( filecount++ ))
read -u4 -r -d $'\0' line
read -u4 line
done
echo 'BEGIN TRANSACTION;' >&3
for line in "${tagfiles[@]}"

View File

@ -10,7 +10,7 @@ gettaskinfos() {
FROM tasks
WHERE id='$1';
' >&3
read -u4 -r -d $'\0' line
read -u4 line
taskid=${line%%::AtOM:SQL:Sep::*}
rest="${line#*::AtOM:SQL:Sep::}::AtOM:SQL:Sep::"
sourcefileid=${rest%%::AtOM:SQL:Sep::*}

View File

@ -2,7 +2,7 @@
createworker() {
(( ++active ))
read -u4 -r -d $'\0' line
read -u4 line
taskid=${line%%::AtOM:SQL:Sep::*}
rest="${line#*::AtOM:SQL:Sep::}::AtOM:SQL:Sep::"
sourcefileid=${rest%%::AtOM:SQL:Sep::*}

View File

@ -10,7 +10,7 @@ master() {
WHERE status = 0;
'>&3
read -u4 -r -d $'\0' remaining
read -u4 remaining
if (( remaining == 0 ))
then
sleep 0.1
@ -108,7 +108,7 @@ master() {
LIMIT 1;
'>&3
read -u4 -r -d $'\0' ready
read -u4 ready
if (( ready > 0 ))
then
createworker
@ -194,7 +194,7 @@ master() {
LIMIT 1;
' >&3
read -u4 -r -d $'\0' ready
read -u4 ready
if (( active == 0 && ready == 0 ))
then
@ -234,7 +234,7 @@ master() {
WHERE status = 0;
'>&3
read -u4 -r -d $'\0' remaining
read -u4 remaining
done
fi
}

View File

@ -121,7 +121,7 @@ getdstfiles() {
;
SELECT "AtOM:NoMoreFiles";
'>&3
while read -u4 -r -d $'\0' line
while read -u4 line
do
if [[ $line == AtOM:NoMoreFiles ]]
then
@ -159,7 +159,7 @@ renameFile() {
fi
}
while read -u4 -r -d $'\0' line
while read -u4 line
do
if [[ $line == AtOM:NoMoreFiles ]]
then

View File

@ -65,7 +65,6 @@ getConfig
sanityCheck
openDatabase
echo -n "Checking for missing files... "
echo '
SELECT
destination_files.id,
@ -80,7 +79,7 @@ echo 'SELECT "AtOM:NoMoreFiles";' >&3
declare -a \
destination_names \
files
read -u4 -r -d $'\0' line
read -u4 line
until [[ $line == AtOM:NoMoreFiles ]]
do
id=${line%%::AtOM:SQL:Sep::*}
@ -88,11 +87,12 @@ do
destination_names[id]=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
files[id]=${rest}
read -u4 -r -d $'\0' line
read -u4 line
done
echo 'BEGIN TRANSACTION;' >&3
echo -n "Checking for missing files... "
for index in "${!files[@]}"
do
destination=${destination_names[index]}

View File

@ -65,22 +65,25 @@ getConfig
sanityCheck
openDatabase
checkwanted() {
Select id <<<"filename = $1"
}
for destination in "${!destinationpath[@]}"
do
echo -ne "\rScanning destination $destination... \033[K"
while read -r -d $'\0' filename
while read -r filename
do
sqlfile=${filename//$'\n'/::AtOM:NewLine:SQL:Inline::}
if ! Select destination_files id \
>/dev/null \
<<<"filename = ${sqlfile#${destinationpath["$destination"]}/}"
<<<"filename = ${filename#${destinationpath["$destination"]}/}"
then
echo -e $'\r'"$filename\033[K"
(( remove )) && rm "$filename"
(( remove )) && rm -f "$filename"
echo -n "Scanning destination $destination... "
fi
progressSpin
done < <(find "${destinationpath["$destination"]}" -type f -print0)
done < <(find "${destinationpath["$destination"]}" -type f)
done
echo -en "\r\033[K"

View File

@ -274,7 +274,7 @@ fi
echo 'SELECT IFNULL(
(SELECT last_seen FROM source_files ORDER BY last_seen DESC LIMIT 1),
0);' >&3
read -u4 -r -d $'\0' lastupdate
read -u4 lastupdate
if ! [[ "$output" == - ]]
then
@ -369,11 +369,11 @@ COLLATE NOCASE;
SELECT "AtOM:NoMoreFiles";' >&3
read -u4 -r -d $'\0' line
read -u4 line
until [[ $line == AtOM:NoMoreFiles ]]
do
files+=("$line")
read -u4 -r -d $'\0' line
read -u4 line
done
for line in "${files[@]}"
@ -675,7 +675,7 @@ echo '
SELECT "AtOM:NoMoreFiles";' >&3
read -u4 -r -d $'\0' line
read -u4 line
until [[ $line == AtOM:NoMoreFiles ]]
do
artist="${line%%::AtOM:SQL:Sep::*}"
@ -685,7 +685,7 @@ do
artists+=( "$artist" )
maxcountlen=$(( ${#count} > maxcountlen ? ${#count} : maxcountlen ))
maxartistlen=$(( ${#artist} > maxartistlen ? ${#artist} : maxartistlen ))
read -u4 -r -d $'\0' line
read -u4 line
done
head=$(
printf "| # | %'${maxcoutlen}s | %-${maxartistlen}s |" \
@ -714,7 +714,7 @@ echo '
FROM source_files
INNER JOIN mime_types
ON source_files.mime_type=mime_types.id;' >&3
read -u4 -r -d $'\0' line
read -u4 line
totalcount="${line%%::AtOM:SQL:Sep::*}"
maxcountlen=$(printf "%'i" $totalcount)
maxcountlen=${#maxcountlen}
@ -743,7 +743,7 @@ do
INNER JOIN mime_types
ON source_files.mime_type=mime_types.id
WHERE mime_text LIKE "'"$format"'";' >&3
read -u4 -r -d $'\0' line
read -u4 line
count="${line%%::AtOM:SQL:Sep::*}"
rest="${line#*::AtOM:SQL:Sep::}::AtOM:SQL:Sep::"
size="${rest%%::AtOM:SQL:Sep::*}"

View File

@ -131,11 +131,11 @@ echo ') ORDER BY bitrate;' >&3
echo 'SELECT "AtOM:NoMoreFiles";' >&3
read -u4 -r -d $'\0' line
read -u4 line
until [[ $line == AtOM:NoMoreFiles ]]
do
echo "${line//::AtOM:SQL:Sep::/$'\t'}"
read -u4 -r -d $'\0' line
read -u4 line
done
closeDatabase

View File

@ -149,11 +149,11 @@ cat >&3 <<-EOSelect
SELECT "AtOM:NoMoreFiles";
EOSelect
read -u4 -r -d $'\0' line
read -u4 line
until [[ $line == AtOM:NoMoreFiles ]]
do
lines+=( "$line" )
read -u4 -r -d $'\0' line
read -u4 line
done
for line in "${lines[@]}"