Bash脚本将新目录添加到PostgreSQL表中

时间:2012-06-29 22:35:44

标签: bash postgresql

我正在尝试编写一个列出目录的脚本并创建一个SQL脚本来插入这些目录,问题是我只想插入新目录,这是我到目前为止所拥有的:

#If file doesn't exist add the search path test
if [ ! -e  /home/aydin/movies.sql ] 
then
    echo "SET SEARCH_PATH TO noti_test;" >> /home/aydin/movies.sql;
fi
cd /media/htpc/
for i in *
do
    #for each directory escape any single quotes
    movie=$(echo $i | sed "s:':\\\':g" )
    #build sql insert string
    insertString="INSERT INTO movies (movie) VALUES (E'$movie');";
    #if sql string exists in file already   
    if grep -Fxq "$insertString" /home/aydin/movies.sql
    then
        #comment out string
        sed -i "s/$insertString/--$insertString/g" /home/aydin/movies.sql
    else
        #add sql string
            echo $insertString >> /home/aydin/movies.sql;
    fi
done;
#execute script
psql -U "aydin.hassan" -d "aydin_1.0" -f /home/aydin/movies.sql;

它似乎与一件事不同,脚本无法识别带有单引号的条目,因此在没有新目录的情况下再次运行脚本时,这就是文件的样子:

--INSERT INTO movies (movie) VALUES (E'007, Moonraker (1979)');
--INSERT INTO movies (movie) VALUES (E'007, Octopussy (1983)');
INSERT INTO movies (movie) VALUES (E'007, On Her Majesty\'s Secret Service (1969)');  

我愿意接受关于更好的方法来做到这一点的建议,我的过程似乎相当长,效率低下:)

3 个答案:

答案 0 :(得分:1)

脚本看起来对我很好。考虑修订版本(未经测试):

#! /bin/bash
#If file doesn't exist add the search path test
if [ ! -e  /home/aydin/movies.sql ] 
then
    echo 'SET search_path=noti_test;' > /home/aydin/movies.sql;
fi
cd /media/htpc/
for i in *
do
    #build sql insert string - single quotes work fine inside dollar-quoting
    insertString="INSERT INTO movies (movie) SELECT \$x\$$movie\$x\$
WHERE NOT EXISTS (SELECT 1 FROM movies WHERE movie = \$x\$$movie\$x\$);"

    #no need for grep. SQL is self-contained.
    echo $insertString >> /home/aydin/movies.sql
done

#execute script
psql -U "aydin.hassan" -d "aydin_1.0" -f /home/aydin/movies.sql;
  • 要开始新文件,请使用>代替>>

  • 对不带变量的字符串常量使用单引号'

  • 使用PostgreSQL dollar-quoting,因此您不必担心字符串中的单引号。您必须转义shell中的$字符才能删除它在shell中的特殊含义 使用“不可能”字符串作为美元引用,因此它不会出现在字符串中。如果你没有,你可以测试一下quote-string并在不太可能的情况下改变它,以确保它是匹配的。

  • 使用SELECT .. WHERE NOT EXISTS进行INSERT以自动阻止重新插入已存在的条目。这样可以完全防止表中的重复条目 - 而不仅仅是新条目中的重复条目。

  • movies.movie上的索引(可能,但不一定是UNIQUE)会加速INSERT。

答案 1 :(得分:0)

为什么要打扰grepsed而不只是让数据库检测到重复项?

movie上添加唯一索引,并在每次运行时创建一个新的(临时)插入脚本,然后使用autocommit(默认)或-v ON_ERROR_ROLLBACK=1选项psql执行它。要获取电影数据库的完整插入脚本,请使用--column-inserts pg_dump选项转储它。

希望这有帮助。

答案 2 :(得分:0)

有一个名为 incron 的实用程序守护程序,只要某个文件写入监视目录,它就会触发您的脚本。它使用内核事件,没有循环 - 仅限Linux。

在其配置(完整文件路径)中:

/media/htpc IN_CLOSE_WRITE /home/aydin/added.sh $@/$#

然后最简单的 adder.sh 脚本,没有任何参数检查:

#!/bin/bash
cat <<-EOsql | psql -U "aydin.hassan" -d "aydin_1.0"
INSERT INTO movies (movie) VALUES (E'$1');
EOsql

您可以在一个目录中拥有数千个文件,而不会出现您可能面对原始脚本的问题。