无法在 bash 脚本中将变量传递给 sqlite(而其他变量确实会传递)



所以我有一个digikam数据库。我已经将一些vid文件从MPG转换为MP4(并懒洋洋地决定将".MP4"附加到".MPG"文件名上(所以.MPG.MP4是一个丑陋的结果…(,而不是替换原始扩展名,这实际上使代码方面的操作更容易(,将它们导入回来,并希望将标记复制到转换后的文件中。该数据库是sqlite3数据库。ImageTags表包含imageid字段(与Images.id字段匹配(和tagid字段。这是一个一对多的交易,所以如果你的imageid是123,并且你分配了tagid 3和4,你会得到两行数据,每个标签一行。

由于sqlite不支持变量,我发现了(多亏了SO(如何将shell脚本中的变量引用到查询中。这段代码很粗糙,只是到了尝试获得正确输出的地步,而不是添加到数据库的地步,但想法是从数据库中获取转换后的mp4文件id,获取原始文件id,然后用新的替换ImageTags.imageid,然后以任何方式将它们作为新行添加到数据库中,还没有决定。。。下面假设一个测试用例只是吐出一个csv文件,然后我可以将其添加到表中,但我想我想以某种INSERT方式来做这件事,但这并不是我的问题;我还没有写那部分,这仍然处于POC状态。

到目前为止,我几乎所有的代码都在工作,尽管很难看,但有一部分除外:这一行不起作用。

SELECT REPLACE(ImageTags.imageid,"${original_imageid}","${mp4_imageid}"),ImageTags.tagid

因此,以下代码的输出是,例如:

mp4 file is 89877
original file is 39967
39967,13
39967,3
39967,152
39967,212

我所希望的是

mp4 file is 89877
original file is 39967
89877,13
89877,3
89877,152
89877,212

所以REPLACE语句不接受变量。我已经用静态值做了测试,它可以用静态值工作。让我困惑的是,SQL的其余部分愉快地接受了

"${file}"

声明没有问题,但似乎阻碍了

"${original_imageid}","${mp4_imageid}"

我玩过各种单引号、无引号、无大括号等。我想知道这是否应该用Python重写,但我担心我会遇到同样的问题。我想知道这是不是处理语句的顺序问题。更糟糕的是,这远远超出了REPLACE声明的预期。我已经阅读了关于如何使用REPLACE的文档和许多示例,但他们似乎没有任何在shell脚本中使用变量的示例。

代码(不要恨我(:

#!/usr/bin/env bash
db=/home/john/media/digikam4.db 
find /home/john/media -type f -iname "*.mp*g" -print0 | 
while read -d $'' file
do
mp4_imageid=$(sqlite3 -ascii ${db} "
SELECT Images.id
FROM Images
JOIN Albums
ON Images.album = Albums.id
JOIN AlbumRoots
ON Albums.albumRoot = AlbumRoots.id
WHERE AlbumRoots.specificPath || Albums.relativePath || "/" || Images.name
IS "${file}" || ".mp4"
")
echo "mp4 file is $mp4_imageid"

original_imageid=$(sqlite3 -ascii ${db} "
SELECT Images.id
FROM Images
JOIN Albums 
ON Images.album = Albums.id
JOIN AlbumRoots
ON Albums.albumRoot = AlbumRoots.id
WHERE AlbumRoots.specificPath || Albums.relativePath || "/" || Images.name
IS "${file}"
")
echo "original file is $original_imageid"
sqlite3 -csv ${db} "
SELECT REPLACE(ImageTags.imageid,"${original_imageid}","${mp4_imageid}"),ImageTags.tagid
FROM ImageTags
JOIN Images 
ON Images.id = ImageTags.imageid
JOIN Albums
ON Images.album = Albums.id
JOIN AlbumRoots
ON Albums.albumRoot = AlbumRoots.id
WHERE AlbumRoots.specificPath || Albums.relativePath || "/" || Images.name
IS "${file}"
"
done

所以问题是我使用了-ascii。我应该用引号。它现在给出了预期的输出。

因此,它需要将变量中的数据设置为sql文本,并且-quote参数可以工作所以这个代码有效:

#!/usr/bin/env bash
db=/home/john/media/digikam4.db 
find /home/john/media -type f -iname "*.mp*g" -print0 | 
while read -d $'' file
do
mp4_imageid=$(sqlite3 -quote ${db} "
SELECT Images.id
FROM Images
JOIN Albums
ON Images.album = Albums.id
JOIN AlbumRoots
ON Albums.albumRoot = AlbumRoots.id
WHERE AlbumRoots.specificPath || Albums.relativePath || "/" || Images.name
IS "${file}" || ".mp4"
")
echo "mp4 file is $mp4_imageid"

original_imageid=$(sqlite3 -quote ${db} "
SELECT Images.id
FROM Images
JOIN Albums 
ON Images.album = Albums.id
JOIN AlbumRoots
ON Albums.albumRoot = AlbumRoots.id
WHERE AlbumRoots.specificPath || Albums.relativePath || "/" || Images.name
IS "${file}"
")
echo "original file is $original_imageid"
sqlite3 -csv ${db} "
SELECT REPLACE(ImageTags.imageid,"${original_imageid}","${mp4_imageid}"),ImageTags.tagid
FROM ImageTags
JOIN Images 
ON Images.id = ImageTags.imageid
JOIN Albums
ON Images.album = Albums.id
JOIN AlbumRoots
ON Albums.albumRoot = AlbumRoots.id
WHERE AlbumRoots.specificPath || Albums.relativePath || "/" || Images.name
IS "${file}"
"
done

最新更新