Compare commits
2 Commits
a663b412a8
...
ee119f07a4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee119f07a4 | ||
|
|
c99825912f |
7
configure
vendored
7
configure
vendored
@ -1,25 +1,28 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# defaults
|
# Default install prefix if --prefix= is not provided
|
||||||
default_prefix=/usr/local
|
default_prefix=/usr/local
|
||||||
#default_bindir=$default_prefix/bin
|
#default_bindir=$default_prefix/bin
|
||||||
#default_libdir=$default_prefix/lib
|
#default_libdir=$default_prefix/lib
|
||||||
#default_sharedir=$default_prefix/share
|
#default_sharedir=$default_prefix/share
|
||||||
|
|
||||||
|
# Parse command-line arguments (only --prefix=VALUE is supported)
|
||||||
while (( $# ))
|
while (( $# ))
|
||||||
do
|
do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
--prefix=*) prefix="${1#*=}"
|
--prefix=*) prefix="${1#*=}" # Strip the "--prefix=" portion to get the value
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
shift
|
shift
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Derive install directories from prefix (or default_prefix if unset)
|
||||||
bindir="${prefix:-$default_prefix}"/bin
|
bindir="${prefix:-$default_prefix}"/bin
|
||||||
libdir="${prefix:-$default_prefix}"/lib/AtOM
|
libdir="${prefix:-$default_prefix}"/lib/AtOM
|
||||||
sharedir="${prefix:-$default_prefix}"/share/AtOM
|
sharedir="${prefix:-$default_prefix}"/share/AtOM
|
||||||
docdir="${prefix:-$default_prefix}"/share/doc/AtOM
|
docdir="${prefix:-$default_prefix}"/share/doc/AtOM
|
||||||
|
|
||||||
|
# Write Makefile.in so the Makefile can substitute real paths at build time
|
||||||
cat > Makefile.in <<-EOMakefile.in
|
cat > Makefile.in <<-EOMakefile.in
|
||||||
bindir = "$bindir"
|
bindir = "$bindir"
|
||||||
libdir = "$libdir"
|
libdir = "$libdir"
|
||||||
|
|||||||
@ -1,27 +1,47 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright © 2012-2026 ScriptFanix
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# A copy of the GNU General Public License v3 is includded in the LICENSE file
|
||||||
|
# at the root of the project.
|
||||||
|
|
||||||
getConfig() {
|
getConfig() {
|
||||||
|
# Read the config file line by line; 'key' gets the first word, 'value'
|
||||||
|
# the rest
|
||||||
while read key value
|
while read key value
|
||||||
do
|
do
|
||||||
case $key in
|
case $key in
|
||||||
'#'*)
|
'#'*)
|
||||||
#comment
|
#comment - skip comment lines
|
||||||
;;
|
;;
|
||||||
'')
|
'')
|
||||||
#empty line
|
#empty line - skip blank lines
|
||||||
;;
|
;;
|
||||||
'[general]')
|
'[general]')
|
||||||
|
# Switch parsing context to the [general] section
|
||||||
context=General
|
context=General
|
||||||
;;
|
;;
|
||||||
'[source]')
|
'[source]')
|
||||||
|
# Switch parsing context to the [source] section
|
||||||
context=Source
|
context=Source
|
||||||
;;
|
;;
|
||||||
\[*\])
|
\[*\])
|
||||||
|
# Any other [section] header is a destination name
|
||||||
context=Destination
|
context=Destination
|
||||||
destination="${key#[}"
|
destination="${key#[}"
|
||||||
destination="${destination%]}"
|
destination="${destination%]}"
|
||||||
destinations+=("${destination%]}")
|
destinations+=("${destination%]}") # Append to list of destinations
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
|
# Dispatch key=value to the handler for the current section context
|
||||||
getConfig$context
|
getConfig$context
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
@ -1,30 +1,50 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright © 2012-2026 ScriptFanix
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# A copy of the GNU General Public License v3 is includded in the LICENSE file
|
||||||
|
# at the root of the project.
|
||||||
|
|
||||||
getConfigDestination() {
|
getConfigDestination() {
|
||||||
case "$key" in
|
case "$key" in
|
||||||
'enabled')
|
'enabled')
|
||||||
|
# 1 = process this destination, 0 = skip it
|
||||||
destinationenabled["$destination"]="$value"
|
destinationenabled["$destination"]="$value"
|
||||||
;;
|
;;
|
||||||
'path')
|
'path')
|
||||||
|
# Strip trailing slash for consistency
|
||||||
destinationpath["$destination"]="${value%/}"
|
destinationpath["$destination"]="${value%/}"
|
||||||
;;
|
;;
|
||||||
'format')
|
'format')
|
||||||
case "$value" in
|
case "$value" in
|
||||||
'mp3')
|
'mp3')
|
||||||
destinationformat["$destination"]=mp3
|
destinationformat["$destination"]=mp3
|
||||||
|
# Flag that lame must be present
|
||||||
lameneeded=1
|
lameneeded=1
|
||||||
# MP3 can't handfle more than 2 channels
|
# MP3 can't handle more than 2 channels
|
||||||
[[ -z ${destinationchannels["$destination"]} ]] \
|
[[ -z ${destinationchannels["$destination"]} ]] \
|
||||||
&& destinationchannels["$destination"]=2
|
&& destinationchannels["$destination"]=2
|
||||||
;;
|
;;
|
||||||
'opus')
|
'opus')
|
||||||
destinationformat["$destination"]=opus
|
destinationformat["$destination"]=opus
|
||||||
|
# Flag that opusenc must be present
|
||||||
opusencneeded=1
|
opusencneeded=1
|
||||||
;;
|
;;
|
||||||
'vorbis')
|
'vorbis')
|
||||||
destinationformat["$destination"]=vorbis
|
destinationformat["$destination"]=vorbis
|
||||||
|
# Flag that oggenc must be present
|
||||||
oggencneeded=1
|
oggencneeded=1
|
||||||
;;
|
;;
|
||||||
'copy')
|
'copy')
|
||||||
|
# Files are copied/hardlinked as-is
|
||||||
destinationformat["$destination"]=copy
|
destinationformat["$destination"]=copy
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
@ -34,6 +54,7 @@ getConfigDestination() {
|
|||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
'quality')
|
'quality')
|
||||||
|
# Vorbis-only: oggenc quality scale (integer, typically 0-10)
|
||||||
expr='^[0-9]*$'
|
expr='^[0-9]*$'
|
||||||
if ! [[ $value =~ $expr ]]
|
if ! [[ $value =~ $expr ]]
|
||||||
then
|
then
|
||||||
@ -46,27 +67,32 @@ getConfigDestination() {
|
|||||||
destinationquality["$destination"]="$value"
|
destinationquality["$destination"]="$value"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Invalid parameter \"$key\" for format \"${destinationformat["$destination"]}\"" >&2
|
echo "Invalid parameter '$key' for" \
|
||||||
|
"format" \
|
||||||
|
"'${destinationformat["$destination"]}'" >&2
|
||||||
exit $EFMTINVPARM
|
exit $EFMTINVPARM
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
'normalize')
|
'normalize')
|
||||||
|
# Whether to normalize audio volume (via sox --norm)
|
||||||
case $value in
|
case $value in
|
||||||
'true'|'on'|'yes')
|
'true'|'on'|'yes'|'1')
|
||||||
destinationnormalize["$destination"]=1
|
destinationnormalize["$destination"]=1
|
||||||
;;
|
;;
|
||||||
'false'|'off'|'no')
|
'false'|'off'|'no'|'0')
|
||||||
destinationnormalize["$destination"]=0
|
destinationnormalize["$destination"]=0
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "normalize takes values:" \
|
echo "normalize takes values:" \
|
||||||
"'yes' ,'true' ,'on', 'no', 'false',"\
|
"'yes' ,'true' ,'on', '1', 'no'," \
|
||||||
"'off'"
|
"'false','off', '0'"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
'bitrate')
|
'bitrate')
|
||||||
|
# Opus/MP3: target bitrate in kbps
|
||||||
|
# integer only; Bash doesn't support floats
|
||||||
expr='^[0-9]*$'
|
expr='^[0-9]*$'
|
||||||
if ! [[ $value =~ $expr ]]
|
if ! [[ $value =~ $expr ]]
|
||||||
then
|
then
|
||||||
@ -88,6 +114,7 @@ getConfigDestination() {
|
|||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
'loss')
|
'loss')
|
||||||
|
# Opus Forward Error Correction: expected packet loss percentage (0-100)
|
||||||
expr='^[0-9]*$'
|
expr='^[0-9]*$'
|
||||||
if ! [[ $value =~ $expr ]]
|
if ! [[ $value =~ $expr ]]
|
||||||
then
|
then
|
||||||
@ -100,12 +127,15 @@ getConfigDestination() {
|
|||||||
destinationloss["$destination"]="$value"
|
destinationloss["$destination"]="$value"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "$Invalid parameter \"$key\" for format \"${destinationformat["$destination"]}\"" >&2
|
echo "Invalid parameter '$key' for" \
|
||||||
|
"format" \
|
||||||
|
"'${destinationformat["$destination"]}'" >&2
|
||||||
exit $EFMTINVPARM
|
exit $EFMTINVPARM
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
'channels')
|
'channels')
|
||||||
|
# Up/downmix to this many channels if needed
|
||||||
expr='^[0-9]*$'
|
expr='^[0-9]*$'
|
||||||
if ! [[ $value =~ $expr ]]
|
if ! [[ $value =~ $expr ]]
|
||||||
then
|
then
|
||||||
@ -116,6 +146,7 @@ getConfigDestination() {
|
|||||||
destinationchannels["$destination"]=$value
|
destinationchannels["$destination"]=$value
|
||||||
;;
|
;;
|
||||||
'frequency')
|
'frequency')
|
||||||
|
# Resample to this sample rate in Hz (e.g. 44100)
|
||||||
expr='^[0-9]*$'
|
expr='^[0-9]*$'
|
||||||
if ! [[ $value =~ $expr ]]
|
if ! [[ $value =~ $expr ]]
|
||||||
then
|
then
|
||||||
@ -126,21 +157,24 @@ getConfigDestination() {
|
|||||||
destinationfrequency["$destination"]=$value
|
destinationfrequency["$destination"]=$value
|
||||||
;;
|
;;
|
||||||
'noresample')
|
'noresample')
|
||||||
|
# MP3-only: prevent lame from auto-downsampling at low
|
||||||
|
# bitrates
|
||||||
case $value in
|
case $value in
|
||||||
'true'|'on'|'yes')
|
'true'|'on'|'yes'|'1')
|
||||||
destinationnoresample["$destination"]=1
|
destinationnoresample["$destination"]=1
|
||||||
;;
|
;;
|
||||||
'false'|'off'|'no')
|
'false'|'off'|'no'|'0')
|
||||||
destinationnoresample["$destination"]=0
|
destinationnoresample["$destination"]=0
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "noresample takes values:" \
|
echo "noresample takes values:" \
|
||||||
"'yes' ,'true' ,'on', 'no', 'false',"\
|
"'yes' ,'true' ,'on', '1', 'no',"\
|
||||||
"'off'"
|
"'false','off', '0'"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
'rename')
|
'rename')
|
||||||
|
# File rename pattern using %{tag} tokens
|
||||||
case "$value" in
|
case "$value" in
|
||||||
*/*)
|
*/*)
|
||||||
destinationrenamepath["$destination"]="${value%/*}"
|
destinationrenamepath["$destination"]="${value%/*}"
|
||||||
@ -149,46 +183,62 @@ getConfigDestination() {
|
|||||||
destinationrename["$destination"]="${value##*/}"
|
destinationrename["$destination"]="${value##*/}"
|
||||||
;;
|
;;
|
||||||
'fat32compat')
|
'fat32compat')
|
||||||
|
# Strip FAT32-illegal characters (? \ < > : * | ")
|
||||||
|
# trim spaces/dots
|
||||||
case $value in
|
case $value in
|
||||||
'true'|'on'|'yes')
|
'true'|'on'|'yes'|'1')
|
||||||
destinationfat32compat["$destination"]=1
|
destinationfat32compat["$destination"]=1
|
||||||
;;
|
;;
|
||||||
'false'|'off'|'no')
|
'false'|'off'|'no'|'0')
|
||||||
destinationfat32compat["$destination"]=0
|
destinationfat32compat["$destination"]=0
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "fat32compat takes values:" \
|
echo "fat32compat takes values:" \
|
||||||
"'yes' ,'true' ,'on', 'no', 'false',"\
|
"'yes' ,'true' ,'on', '1', 'no',"\
|
||||||
"'off'"
|
"'false','off', '0'"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
'ascii-only')
|
'ascii-only')
|
||||||
|
# Transliterate Unicode filenames to ASCII using
|
||||||
|
#Requires Perl Text::Unidecode
|
||||||
case $value in
|
case $value in
|
||||||
'true'|'on'|'yes')
|
'true'|'on'|'yes'|'1')
|
||||||
destinationascii["$destination"]=1
|
destinationascii["$destination"]=1
|
||||||
|
# Signal that the perl coprocess will
|
||||||
|
# be needed
|
||||||
textunidecodeneeded=1
|
textunidecodeneeded=1
|
||||||
;;
|
;;
|
||||||
'false'|'off'|'no')
|
'false'|'off'|'no'|'0')
|
||||||
destinationascii["$destination"]=0
|
destinationascii["$destination"]=0
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "ascii-only takes values:" \
|
echo "ascii-only takes values:" \
|
||||||
"'yes' ,'true' ,'on', 'no', 'false',"\
|
"'yes' ,'true' ,'on', '1', 'no',"\
|
||||||
"'off'"
|
"'false','off', '0'"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
'skip_mime-type')
|
'skip_mime-type')
|
||||||
|
# Accumulate pipe-separated list of mime patterns to
|
||||||
|
# exclude entirely
|
||||||
destinationskipmime[$destination]="${destinationskipmime[$destination]:+${destinationskipmime[$destination]}|}$value"
|
destinationskipmime[$destination]="${destinationskipmime[$destination]:+${destinationskipmime[$destination]}|}$value"
|
||||||
;;
|
;;
|
||||||
'copy_mime-type')
|
'copy_mime-type')
|
||||||
|
# Accumulate pipe-separated list of mime patterns to
|
||||||
|
# copy verbatim (action=2)
|
||||||
destinationcopymime[$destination]="${destinationcopymime[$destination]:+${destinationcopymime[$destination]}|}$value"
|
destinationcopymime[$destination]="${destinationcopymime[$destination]:+${destinationcopymime[$destination]}|}$value"
|
||||||
;;
|
;;
|
||||||
'copy_extension')
|
'copy_extension')
|
||||||
|
# Accumulate pipe-separated list of file extensions to
|
||||||
|
# copy verbatim
|
||||||
destinationcopyext[$destination]="${destinationcopyext[$destination]:+${destinationcopyext[$destination]}|}$value"
|
destinationcopyext[$destination]="${destinationcopyext[$destination]:+${destinationcopyext[$destination]}|}$value"
|
||||||
;;
|
;;
|
||||||
'higher-than')
|
'higher-than')
|
||||||
|
# Only re-encode source files with bitrate ABOVE this
|
||||||
|
# threshold (kbps)
|
||||||
|
# Files at or below this bitrate will be
|
||||||
|
# hardlinked/copied instead
|
||||||
expr='^[0-9]*$'
|
expr='^[0-9]*$'
|
||||||
if ! [[ $value =~ $expr ]]
|
if ! [[ $value =~ $expr ]]
|
||||||
then
|
then
|
||||||
|
|||||||
@ -1,7 +1,23 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright © 2012-2026 ScriptFanix
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# A copy of the GNU General Public License v3 is includded in the LICENSE file
|
||||||
|
# at the root of the project.
|
||||||
|
|
||||||
getConfigGeneral() {
|
getConfigGeneral() {
|
||||||
case $key in
|
case $key in
|
||||||
'max-load')
|
'max-load')
|
||||||
|
# Target system 1-minute load average
|
||||||
|
# concurrency is adjusted to stay near this
|
||||||
expr='^[0-9]*$'
|
expr='^[0-9]*$'
|
||||||
if [[ $value =~ $expr ]]
|
if [[ $value =~ $expr ]]
|
||||||
then
|
then
|
||||||
@ -13,6 +29,7 @@ getConfigGeneral() {
|
|||||||
unset expr
|
unset expr
|
||||||
;;
|
;;
|
||||||
'load-interval')
|
'load-interval')
|
||||||
|
# How often (seconds) to adjust worker count
|
||||||
expr='^[0-9]*$'
|
expr='^[0-9]*$'
|
||||||
if [[ $value =~ $expr ]]
|
if [[ $value =~ $expr ]]
|
||||||
then
|
then
|
||||||
@ -48,6 +65,7 @@ getConfigGeneral() {
|
|||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
2)
|
2)
|
||||||
|
# Best-effort class; niceness 0 (highest) to 7 (lowest)
|
||||||
if [ -n "$niceness" ] \
|
if [ -n "$niceness" ] \
|
||||||
&& (( niceness >= 0 && niceness <= 7 ))
|
&& (( niceness >= 0 && niceness <= 7 ))
|
||||||
then
|
then
|
||||||
@ -59,10 +77,11 @@ getConfigGeneral() {
|
|||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
3)
|
3)
|
||||||
|
# Idle class: only gets I/O when no other process needs it
|
||||||
ionice="ionice -c3 "
|
ionice="ionice -c3 "
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Invalid ionice parameters $value"\
|
echo "Invalid ionice class $value"\
|
||||||
>&2
|
>&2
|
||||||
exit $EIONICE
|
exit $EIONICE
|
||||||
;;
|
;;
|
||||||
@ -70,15 +89,23 @@ getConfigGeneral() {
|
|||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
'temporary-directory')
|
'temporary-directory')
|
||||||
|
# Directory for
|
||||||
|
# * SQLite FIFOs
|
||||||
|
# * intermediate WAV files
|
||||||
|
# * debug logs
|
||||||
tempdir="$value"
|
tempdir="$value"
|
||||||
;;
|
;;
|
||||||
'database')
|
'database')
|
||||||
|
# Path to the SQLite database file
|
||||||
database="$value"
|
database="$value"
|
||||||
;;
|
;;
|
||||||
'skip-timestamp-microsec')
|
'skip-timestamp-microsec')
|
||||||
|
# If non-zero, ignore sub-second precision in file timestamps
|
||||||
|
# Useful on filesystems that don't preserve microseconds
|
||||||
skip_us_timestamp="$value"
|
skip_us_timestamp="$value"
|
||||||
;;
|
;;
|
||||||
debug)
|
debug)
|
||||||
|
# Allow config file to raise debug level (but not lower it)
|
||||||
(( value > debug )) && debug=$value
|
(( value > debug )) && debug=$value
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
@ -1,10 +1,27 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright © 2012-2026 ScriptFanix
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# A copy of the GNU General Public License v3 is includded in the LICENSE file
|
||||||
|
# at the root of the project.
|
||||||
|
|
||||||
getConfigSource() {
|
getConfigSource() {
|
||||||
case "$key" in
|
case "$key" in
|
||||||
'path')
|
'path')
|
||||||
|
# Root directory of music collection to transcode from
|
||||||
sourcepath="$value"
|
sourcepath="$value"
|
||||||
;;
|
;;
|
||||||
'skip')
|
'skip')
|
||||||
|
# Directory pattern to exclude from scanning
|
||||||
|
# Multiple 'skip' entries accumulate into this array
|
||||||
skippeddirectories+=( "$value" )
|
skippeddirectories+=( "$value" )
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|||||||
@ -1,6 +1,22 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright © 2012-2026 ScriptFanix
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# A copy of the GNU General Public License v3 is includded in the LICENSE file
|
||||||
|
# at the root of the project.
|
||||||
|
|
||||||
printConfig() {
|
printConfig() {
|
||||||
{
|
{
|
||||||
|
# Build a pipe-delimited table
|
||||||
|
# 'column -t -s|' will transform into columns
|
||||||
echo "General|Config file|$cffile"
|
echo "General|Config file|$cffile"
|
||||||
[ -n "$ionice" ] && echo "|IO Nice|$ionice"
|
[ -n "$ionice" ] && echo "|IO Nice|$ionice"
|
||||||
cat <<-EOF
|
cat <<-EOF
|
||||||
@ -12,24 +28,29 @@ printConfig() {
|
|||||||
|
|
||||||
Source|Path|$sourcepath
|
Source|Path|$sourcepath
|
||||||
EOF
|
EOF
|
||||||
|
# Print skipped directories
|
||||||
|
# use a continuation prefix after the first
|
||||||
for prune_expression in "${skippeddirectories[@]}"
|
for prune_expression in "${skippeddirectories[@]}"
|
||||||
do
|
do
|
||||||
(( printed )) \
|
(( printed )) \
|
||||||
&& echo -n ' | |' \
|
&& echo -n ' | |' \
|
||||||
|| echo -n ' |Skipped directories|'
|
|| echo -n ' |Skipped directories|'
|
||||||
echo "$prune_expression"
|
echo "$prune_expression"
|
||||||
printed=1
|
printed=1
|
||||||
done
|
done
|
||||||
unset printed
|
unset printed
|
||||||
|
# Loop over destinations and print their settings
|
||||||
|
# use the destination name as a key into the associative arrays
|
||||||
for destination in ${destinations[@]}
|
for destination in ${destinations[@]}
|
||||||
do
|
do
|
||||||
cat <<-EOF
|
cat <<-EOF
|
||||||
|
|
||||||
$destination|Path|${destinationpath["$destination"]}
|
$destination|Path|${destinationpath["$destination"]}
|
||||||
|Enabled|${destinationenabled["$destination"]}
|
|Enabled|${destinationenabled["$destination"]}
|
||||||
|Format|${destinationformat["$destination"]}
|
|Format|${destinationformat["$destination"]}
|
||||||
|Quality|${destinationquality["$destination"]}
|
|Quality|${destinationquality["$destination"]}
|
||||||
EOF
|
EOF
|
||||||
|
# Show format-specific fields
|
||||||
if [[ ${destinationformat["$destination"]} == opus ]]
|
if [[ ${destinationformat["$destination"]} == opus ]]
|
||||||
then
|
then
|
||||||
echo " |Expected loss|${destinationloss["$destination"]}"
|
echo " |Expected loss|${destinationloss["$destination"]}"
|
||||||
@ -47,6 +68,7 @@ printConfig() {
|
|||||||
|Path Change|${destinationrenamepath["$destination"]}
|
|Path Change|${destinationrenamepath["$destination"]}
|
||||||
|File Rename|${destinationrename["$destination"]}
|
|File Rename|${destinationrename["$destination"]}
|
||||||
EOF
|
EOF
|
||||||
|
# Display pipe-separated mime lists: one entry per row
|
||||||
[ -n "${destinationskipmime["$destination"]}" ] \
|
[ -n "${destinationskipmime["$destination"]}" ] \
|
||||||
&& echo " |Skipped mime-types|${destinationskipmime["$destination"]//\|/
|
&& echo " |Skipped mime-types|${destinationskipmime["$destination"]//\|/
|
||||||
| |}"
|
| |}"
|
||||||
@ -57,5 +79,5 @@ printConfig() {
|
|||||||
&& echo " |Copied extensions|${destinationcopyext["$destination"]//\|/
|
&& echo " |Copied extensions|${destinationcopyext["$destination"]//\|/
|
||||||
| |}"
|
| |}"
|
||||||
done
|
done
|
||||||
}|column -t -s'|'
|
}|column -t -s'|' # Format as aligned columns using '|' as delimiter
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,22 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright © 2012-2026 ScriptFanix
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# A copy of the GNU General Public License v3 is includded in the LICENSE file
|
||||||
|
# at the root of the project.
|
||||||
|
|
||||||
|
|
||||||
|
# writeConfig() generates a new atom.cfg from the current in-memory settings.
|
||||||
|
# Output is sent to stdout so callers can redirect it to any config file path.
|
||||||
|
# Each setting is annotated with a description.
|
||||||
writeConfig() {
|
writeConfig() {
|
||||||
cat <<-EOCfg
|
cat <<-EOCfg
|
||||||
[general]
|
[general]
|
||||||
@ -47,6 +64,7 @@ path $sourcepath
|
|||||||
# * skip <directory>: String. Files in <directory> will be ignored. Note that
|
# * skip <directory>: String. Files in <directory> will be ignored. Note that
|
||||||
# <directory> can be any expression accepted by find.
|
# <directory> can be any expression accepted by find.
|
||||||
EOCfg
|
EOCfg
|
||||||
|
# Emit one skip line per skipped directory
|
||||||
for dir in "${skippeddirectories[@]}"
|
for dir in "${skippeddirectories[@]}"
|
||||||
do
|
do
|
||||||
echo $'skip\t\t\t'"$dir"
|
echo $'skip\t\t\t'"$dir"
|
||||||
@ -55,6 +73,7 @@ path $sourcepath
|
|||||||
|
|
||||||
|
|
||||||
EOCfg
|
EOCfg
|
||||||
|
# Emit one section per configured destination
|
||||||
for destination in "${destinations[@]}"
|
for destination in "${destinations[@]}"
|
||||||
do
|
do
|
||||||
cat <<-EOCfg
|
cat <<-EOCfg
|
||||||
@ -190,6 +209,8 @@ bitrate ${destinationquality["$destination"]}
|
|||||||
# be included in that destination. For more than one mime-type, use multiple
|
# be included in that destination. For more than one mime-type, use multiple
|
||||||
# times, as needed. The '*' character is a wildcard.
|
# times, as needed. The '*' character is a wildcard.
|
||||||
EOCfg
|
EOCfg
|
||||||
|
# Emit one skip_mime-type line per MIME pattern (pipe-separated
|
||||||
|
# in the array)
|
||||||
destinationskipmime["$destination"]="${destinationskipmime["$destination"]}|"
|
destinationskipmime["$destination"]="${destinationskipmime["$destination"]}|"
|
||||||
while [[ ${destinationskipmime["$destination"]} =~ \| ]]
|
while [[ ${destinationskipmime["$destination"]} =~ \| ]]
|
||||||
do
|
do
|
||||||
@ -203,6 +224,7 @@ bitrate ${destinationquality["$destination"]}
|
|||||||
# covers and other images to the destination. In fact, AtOM will try to use
|
# covers and other images to the destination. In fact, AtOM will try to use
|
||||||
# hard links instead of copies.
|
# hard links instead of copies.
|
||||||
EOCfg
|
EOCfg
|
||||||
|
# Emit one copy_mime-type line per MIME pattern
|
||||||
destinationcopymime["$destination"]="${destinationcopymime["$destination"]}|"
|
destinationcopymime["$destination"]="${destinationcopymime["$destination"]}|"
|
||||||
while [[ ${destinationcopymime["$destination"]} =~ \| ]]
|
while [[ ${destinationcopymime["$destination"]} =~ \| ]]
|
||||||
do
|
do
|
||||||
@ -213,6 +235,7 @@ bitrate ${destinationquality["$destination"]}
|
|||||||
|
|
||||||
# * copy_extension <extension>: Copy files whose name and with ".<extension>"
|
# * copy_extension <extension>: Copy files whose name and with ".<extension>"
|
||||||
EOCfg
|
EOCfg
|
||||||
|
# Emit one copy_extension line per extension pattern
|
||||||
destinationcopyext["$destination"]="${destinationcopyext["$destination"]}|"
|
destinationcopyext["$destination"]="${destinationcopyext["$destination"]}|"
|
||||||
while [[ ${destinationcopyext["$destination"]} =~ \| ]]
|
while [[ ${destinationcopyext["$destination"]} =~ \| ]]
|
||||||
do
|
do
|
||||||
|
|||||||
@ -1,6 +1,25 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright © 2012-2026 ScriptFanix
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# A copy of the GNU General Public License v3 is includded in the LICENSE file
|
||||||
|
# at the root of the project.
|
||||||
|
|
||||||
copyFiles_action() {
|
copyFiles_action() {
|
||||||
(( cron )) || echo -n $'Copying files...\033[K'
|
(( cron )) || echo -n $'Copying files...\033[K'
|
||||||
|
# Query all destination_files whose last_change doesn't match the
|
||||||
|
# source, restricted to mime_type_actions with action=2 (direct copy,
|
||||||
|
# not transcode).
|
||||||
|
# The join on mime_type_actions ensures we only copy files destined for
|
||||||
|
# a destination that has explicitly mapped this MIME type to action=2.
|
||||||
echo '
|
echo '
|
||||||
SELECT
|
SELECT
|
||||||
source_files.filename,
|
source_files.filename,
|
||||||
@ -22,6 +41,8 @@ copyFiles_action() {
|
|||||||
AND mime_type_actions.action = 2;
|
AND mime_type_actions.action = 2;
|
||||||
|
|
||||||
SELECT "AtOM:NoMoreFiles";' >&3
|
SELECT "AtOM:NoMoreFiles";' >&3
|
||||||
|
# Results are NUL-delimited rows; sentinel value signals end of result
|
||||||
|
# set.
|
||||||
read -u4 -r -d $'\0' line
|
read -u4 -r -d $'\0' line
|
||||||
while ! [[ $line = AtOM:NoMoreFiles ]]
|
while ! [[ $line = AtOM:NoMoreFiles ]]
|
||||||
do
|
do
|
||||||
@ -29,9 +50,14 @@ copyFiles_action() {
|
|||||||
read -u4 -r -d $'\0' line
|
read -u4 -r -d $'\0' line
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Wrap all DB updates in a single transaction for performance.
|
||||||
echo 'BEGIN TRANSACTION;' >&3
|
echo 'BEGIN TRANSACTION;' >&3
|
||||||
for copyfile in "${copyfiles[@]}"
|
for copyfile in "${copyfiles[@]}"
|
||||||
do
|
do
|
||||||
|
# Each row is a single string with columns joined by
|
||||||
|
# ::AtOM:SQL:Sep::.
|
||||||
|
# Strip prefix to extract each field in order, advancing $rest
|
||||||
|
# each time.
|
||||||
sourcefilename=${copyfile%%::AtOM:SQL:Sep::*}
|
sourcefilename=${copyfile%%::AtOM:SQL:Sep::*}
|
||||||
sourcedir=${sourcefilename%/*}
|
sourcedir=${sourcefilename%/*}
|
||||||
rest="${copyfile#*::AtOM:SQL:Sep::}::AtOM:SQL:Sep::"
|
rest="${copyfile#*::AtOM:SQL:Sep::}::AtOM:SQL:Sep::"
|
||||||
@ -45,20 +71,33 @@ copyFiles_action() {
|
|||||||
rest=${rest#*::AtOM:SQL:Sep::}
|
rest=${rest#*::AtOM:SQL:Sep::}
|
||||||
(( count++ ))
|
(( count++ ))
|
||||||
(( cron )) || printf '\b\b\b\b%3i%%' $(( (count * 100) / ${#copyfiles[@]} ))
|
(( cron )) || printf '\b\b\b\b%3i%%' $(( (count * 100) / ${#copyfiles[@]} ))
|
||||||
|
# If this destination uses a rename/path pattern, delegate path
|
||||||
|
# resolution to guessPath(), which looks up the
|
||||||
|
# already-transcoded sibling to find the correct output
|
||||||
|
# directory.
|
||||||
if [ -n "${destinationrenamepath["$destination"]}" ]
|
if [ -n "${destinationrenamepath["$destination"]}" ]
|
||||||
then
|
then
|
||||||
destdir="$(guessPath)"
|
destdir="$(guessPath)"
|
||||||
guessstatus=$?
|
guessstatus=$?
|
||||||
case $guessstatus in
|
case $guessstatus in
|
||||||
1)
|
1)
|
||||||
|
# guessPath found no transcoded
|
||||||
|
# sibling; skip this file entirely.
|
||||||
continue
|
continue
|
||||||
;;
|
;;
|
||||||
2)
|
2)
|
||||||
|
# Transcoded siblings exist but are not
|
||||||
|
# yet up to date; defer this copy until
|
||||||
|
# the next run so the directory is
|
||||||
|
# stable.
|
||||||
(( postponed++ ))
|
(( postponed++ ))
|
||||||
continue
|
continue
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
else
|
else
|
||||||
|
# No rename pattern: mirror the source directory
|
||||||
|
# structure under the destination root, sanitizing each
|
||||||
|
# path component for the target FS.
|
||||||
destdir="${destinationpath["$destination"]}/"
|
destdir="${destinationpath["$destination"]}/"
|
||||||
if [[ $sourcefilename =~ / ]]
|
if [[ $sourcefilename =~ / ]]
|
||||||
then
|
then
|
||||||
@ -79,6 +118,9 @@ copyFiles_action() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
# Try the cheapest copy methods first: reflink (CoW, same
|
||||||
|
# filesystem), then hardlink (csame filesystem), falling back
|
||||||
|
# to a full data copy.
|
||||||
if cp -a --reflink=always \
|
if cp -a --reflink=always \
|
||||||
"$sourcepath/$sourcefilename" \
|
"$sourcepath/$sourcefilename" \
|
||||||
"$destdir" \
|
"$destdir" \
|
||||||
@ -91,6 +133,9 @@ copyFiles_action() {
|
|||||||
"$sourcepath/$sourcefilename" \
|
"$sourcepath/$sourcefilename" \
|
||||||
"$destdir"
|
"$destdir"
|
||||||
then
|
then
|
||||||
|
# Newlines in filenames are stored as a safe inline
|
||||||
|
# placeholder so the value can be embedded in SQL
|
||||||
|
# without breaking row parsing.
|
||||||
destfilename=${sourcefilename//$'\n'/::AtOM:NewLine:SQL:Inline::}
|
destfilename=${sourcefilename//$'\n'/::AtOM:NewLine:SQL:Inline::}
|
||||||
Update destination_files \
|
Update destination_files \
|
||||||
filename \
|
filename \
|
||||||
|
|||||||
@ -1,12 +1,39 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright © 2012-2026 ScriptFanix
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# A copy of the GNU General Public License v3 is includded in the LICENSE file
|
||||||
|
# at the root of the project.
|
||||||
|
|
||||||
checkCopy() {
|
checkCopy() {
|
||||||
|
# Returns true only when the source file is compatible enough with the
|
||||||
|
# destination profile that it can be copied instead of re-encoded.
|
||||||
|
# All three conditions must hold simultaneously.
|
||||||
(
|
(
|
||||||
|
# If the destination doesn't restrict sample rate, any rate is
|
||||||
|
# acceptable. Otherwise the source rate must match exactly.
|
||||||
[ -z "${destinationfrequency[$destination]}" ] \
|
[ -z "${destinationfrequency[$destination]}" ] \
|
||||||
|| (( ${rate:-0} == ${destinationfrequency[$destination]} ))
|
|| (( ${rate:-0} == ${destinationfrequency[$destination]} ))
|
||||||
) && (
|
) && (
|
||||||
|
# If the destination doesn't restrict channel count, any number
|
||||||
|
# is acceptable. Otherwise the source channel count must match
|
||||||
|
# exactly.
|
||||||
[ -z "${destinationchannels[$destination]}" ] \
|
[ -z "${destinationchannels[$destination]}" ] \
|
||||||
|| (( ${channels:-0} == ${destinationchannels[$destination]} ))
|
|| (( ${channels:-0} == ${destinationchannels[$destination]} ))
|
||||||
) && (
|
) && (
|
||||||
|
# Bitrate check: accept if source exactly matches the target
|
||||||
|
# quality setting, OR if a maximum bps ceiling is configured
|
||||||
|
# and the source bitrate is at or below it.
|
||||||
|
# Default of 1000 kbps when bitrate is unknown forces a
|
||||||
|
# re-encode
|
||||||
(( ${bitrate:-1000} == ${destinationquality[$destination]} )) \
|
(( ${bitrate:-1000} == ${destinationquality[$destination]} )) \
|
||||||
|| (
|
|| (
|
||||||
[ -n "${destinationmaxbps[$destination]}" ] \
|
[ -n "${destinationmaxbps[$destination]}" ] \
|
||||||
|
|||||||
@ -1,6 +1,29 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright © 2012-2026 ScriptFanix
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# A copy of the GNU General Public License v3 is includded in the LICENSE file
|
||||||
|
# at the root of the project.
|
||||||
|
|
||||||
guessPath() {
|
guessPath() {
|
||||||
|
# For copy files (action=2) with a rename pattern, we don't know the
|
||||||
|
# output directory ourselves: it was determined when the audio siblings
|
||||||
|
# were transcoded (action=1). We infer it by finding a transcoded
|
||||||
|
# sibling in the same source directory and reading back its destination
|
||||||
|
# path.
|
||||||
|
#
|
||||||
|
# First query: check whether any transcoded sibling is up to date.
|
||||||
|
# The LIKE pattern matches files directly inside $sourcedir only
|
||||||
|
# the NOT LIKE excludes deeper subdirectorie to avoid crossing
|
||||||
|
# boundaries.
|
||||||
echo 'SELECT IFNULL( (
|
echo 'SELECT IFNULL( (
|
||||||
SELECT destination_files.last_change
|
SELECT destination_files.last_change
|
||||||
FROM destination_files
|
FROM destination_files
|
||||||
@ -22,10 +45,17 @@ guessPath() {
|
|||||||
),"0.0");
|
),"0.0");
|
||||||
'>&3
|
'>&3
|
||||||
read -u4 -r -d $'\0' timestamp
|
read -u4 -r -d $'\0' timestamp
|
||||||
|
# IFNULL returns "0.0" when no transcoded sibling exists yet; strip the
|
||||||
|
# decimal and treat as zero to detect the no-sibling case.
|
||||||
if (( ${timestamp/./} == 0 ))
|
if (( ${timestamp/./} == 0 ))
|
||||||
then
|
then
|
||||||
|
# No transcoded sibling found at all
|
||||||
|
# caller should postpone this copy.
|
||||||
return 2
|
return 2
|
||||||
fi
|
fi
|
||||||
|
# Second query: retrieve the actual destination filename of the most
|
||||||
|
# recently updated transcoded sibling so we can derive its parent
|
||||||
|
# directory.
|
||||||
echo 'SELECT IFNULL( (
|
echo 'SELECT IFNULL( (
|
||||||
SELECT destination_files.filename
|
SELECT destination_files.filename
|
||||||
FROM destination_files
|
FROM destination_files
|
||||||
@ -49,8 +79,12 @@ guessPath() {
|
|||||||
read -u4 -r -d $'\0' filename
|
read -u4 -r -d $'\0' filename
|
||||||
if [[ $filename != AtOM:NotFound ]]
|
if [[ $filename != AtOM:NotFound ]]
|
||||||
then
|
then
|
||||||
|
# Strip the filename component to return only the directory
|
||||||
|
# portion.
|
||||||
echo "${filename%/*}"
|
echo "${filename%/*}"
|
||||||
else
|
else
|
||||||
|
# Sibling record exists but has no usable filename — skip this
|
||||||
|
# file.
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,25 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Copyright © 2012-2026 ScriptFanix
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License.
|
||||||
|
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
|
||||||
|
# A copy of the GNU General Public License v3 is includded in the LICENSE file
|
||||||
|
# at the root of the project.
|
||||||
|
|
||||||
copyFiles_matching() {
|
copyFiles_matching() {
|
||||||
|
# Preserve the original file extension so the copy keeps its type
|
||||||
|
# (e.g. .jpg, .png, .cue) regardless of any rename pattern applied to
|
||||||
|
# the base name.
|
||||||
local extension="${filename##*.}"
|
local extension="${filename##*.}"
|
||||||
|
# Try hardlink first (no extra disk space); fall back to a full data
|
||||||
|
# copy if the source and destination are on different filesystems.
|
||||||
if \
|
if \
|
||||||
cp -al \
|
cp -al \
|
||||||
"$sourcepath/$filename" \
|
"$sourcepath/$filename" \
|
||||||
@ -10,6 +29,11 @@ copyFiles_matching() {
|
|||||||
"$sourcepath/$filename" \
|
"$sourcepath/$filename" \
|
||||||
"${destinationpath[$destination]}/$destdir/$destfile.$extension"
|
"${destinationpath[$destination]}/$destdir/$destfile.$extension"
|
||||||
then
|
then
|
||||||
|
# Record the new destination path and copy the source
|
||||||
|
# last_change timestamp via a subquery so the DB reflects when
|
||||||
|
# the source was last modified.
|
||||||
|
# old_filename captures the previous path so stale files can be
|
||||||
|
# cleaned up later.
|
||||||
echo \
|
echo \
|
||||||
"UPDATE destination_files" \
|
"UPDATE destination_files" \
|
||||||
"SET filename=" \
|
"SET filename=" \
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user