微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Bash脚本无法识别现有文件

如何解决Bash脚本无法识别现有文件

我必须编写一个简单的bash脚本,该脚本可以编译多个sql脚本,这些脚本可以使用Oracle SQLPlus convention包含对其他sql脚本的递归引用,因此最终结果将只有一个sql文件,包含所有(可能也是递归)引用的下标的所有语句。

我用以下bash代码创建了一个名为oracle-script-compressor.sh的简单脚本:

#!/bin/bash
#
#
function err () {
    echo $* > "/dev/stderr"
}


function replace_subscripts_placeholders() {
    local PROCESSING_FILENAME=$1
    echo "-- processing file $PROCESSING_FILENAME"
    while read script_line; do
        local script_line_NO_LEAD_SPACE="$(echo -e "${script_line}" | sed -e 's/^[[:space:]]*//')"
        if  [[ $script_line_NO_LEAD_SPACE == \@\@* ]] ; then
            local file_name="./${script_line_NO_LEAD_SPACE#\@\@}"
            echo "-- found reference to file $file_name"
            echo "-- starting with processing,pwd=$PWD"
            # for debug purposes:
            ls -la
            # but this returns always false:
            if [ -f "$file_name" ]; then
                # so this part is never started:
                . replace_subscripts_placeholders $file_name
            else
                err_msg="WARNING: Could not find the referenced file $file_name"
                echo "-- $err_msg"
                err $err_msg
            fi          
        else
            echo "$script_line"
        fi
    done < $PROCESSING_FILENAME 
}

if test -z "$1" ; then
    err "Usage: oracle-script-compressor.sh {file_name_to_process} [> output_file]"
    err "  Be aware,if the referenced files within {file_name_to_process} are not specified by absolute paths,you have to start the script from corresponding directory."
    err "  If the part [> output_file] is omitted,then this script writes to standard output"
    err "  If the part [>> output_file] is used,then the result will be appended to output_file it it exists before the processing"
else
    if [ -f "$1" ]; then
        replace_subscripts_placeholders $1
    else
        echo "file $1 does not exist"
    fi
fi

我陷入了一个有趣的问题-似乎在函数replace_subscripts_placeholders()内部,文件检查

        if [ -f "$file_name" ]; then
            . replace_subscripts_placeholders $file_name
        else
            err_msg="WARNING: Could not find the referenced file $file_name"
            echo "-- $err_msg"
            err $err_msg
        fi          

从不进行递归调用,甚至,即使我删除了if语句并使用正确的引用文件名(确实存在)以递归方式真正调用了该函数,也仍然无法识别出该函数,也没有将其传递到循环中递归调用中引用文件的所有行(然后,找不到错误文件,并且无法执行循环)。

我已经将调试消息添加到脚本中,就像上面在脚本中提到的那样,但是仍然找不到,为什么如果文件位于同一目录中,为什么地狱应该bash找不到文件。脚本放置在

user@mycomputer:/tmp/test$ ls -la
celkem 52
drwxr-xr-x  2 user user  4096 zář 14 21:47 .
drwxrwxrwt 38 root     root     36864 zář 14 21:48 ..
-rw-r--r--  1 user user    51 zář 14 21:45 a.sql
-rw-r--r--  1 user user    51 zář 14 21:45 b.sql
-rw-r--r--  1 user user   590 zář 14 21:46 start.sql
user@mycomputer:/tmp/test$ 

文件start.sql内容如下:

spool output__UpdSch.log
whenever sqlerror exit sql.sqlcode 
--
--
PROMPT a.sql - starting
select to_char(current_timestamp,'YYYY-MM-DD HH24:MI:SS.FF3') as START_TIMESTAMP from dual;
@@a.sql
PROMPT a.sql - finished
select to_char(current_timestamp,'YYYY-MM-DD HH24:MI:SS.FF3') as FINISH_TIMESTAMP from dual;
--
--
PROMPT b.sql - starting
select to_char(current_timestamp,'YYYY-MM-DD HH24:MI:SS.FF3') as START_TIMESTAMP from dual;
@@b.sql
PROMPT b.sql - finished
select to_char(current_timestamp,'YYYY-MM-DD HH24:MI:SS.FF3') as FINISH_TIMESTAMP from dual;
--
--
spool off

如果执行脚本,似乎它可以正确解码文件名,但是bash中仍然存在问题-文件存在的测试始终返回false:

user@mycomputer:/tmp/test$ ~/tmp/oracle-script-compressor.sh start.sql 
-- processing file start.sql
spool output__UpdSch.log
whenever sqlerror exit sql.sqlcode 
--
--
PROMPT a.sql - starting
select to_char(current_timestamp,'YYYY-MM-DD HH24:MI:SS.FF3') as START_TIMESTAMP from dual;
-- found reference to file ./a.sql
-- starting with processing,pwd=/tmp/test
celkem 52
drwxr-xr-x  2 user user  4096 zář 14 21:47 .
drwxrwxrwt 38 root     root     36864 zář 14 21:48 ..
-rw-r--r--  1 user user    51 zář 14 21:45 a.sql
-rw-r--r--  1 user user    51 zář 14 21:45 b.sql
-rw-r--r--  1 user user   590 zář 14 21:46 start.sql
-- WARNING: Could not find the referenced file ./a.sql
WARNING: Could not find the referenced file ./a.sql
PROMPT a.sql - finished
select to_char(current_timestamp,'YYYY-MM-DD HH24:MI:SS.FF3') as START_TIMESTAMP from dual;
-- found reference to file ./b.sql
-- starting with processing,pwd=/tmp/test
celkem 52
drwxr-xr-x  2 user user  4096 zář 14 21:47 .
drwxrwxrwt 38 root     root     36864 zář 14 21:48 ..
-rw-r--r--  1 user user    51 zář 14 21:45 a.sql
-rw-r--r--  1 user user    51 zář 14 21:45 b.sql
-rw-r--r--  1 user user   590 zář 14 21:46 start.sql
-- WARNING: Could not find the referenced file ./b.sql
WARNING: Could not find the referenced file ./b.sql
PROMPT b.sql - finished
select to_char(current_timestamp,'YYYY-MM-DD HH24:MI:SS.FF3') as FINISH_TIMESTAMP from dual;
--
--
spool off
user@mycomputer:/tmp/test$ 

该脚本具有对文件的读取权限,所有文件都位于启动该脚本的同一文件夹中,这也没关系,如果我引用当前目录前缀为“ ./”的文件,是否为没找到。有趣的是,脚本启动期间的检查正确通过了,唯一的问题是在函数内进行搜索...我也尝试过在函数加上“”。没有它,它就没有任何区别。在引用的文件名中也没有尾随空格。。。如果我将函数内部的变量声明为局部变量,也没有区别。 所以我不知道这可能是问题所在,也许我只是看了太久而看不到某些东西-似乎必须是一些琐碎的事情,就像函数是在其他当前目录中启动的一样-(但pwd和ls显示了目录始终是正确的... ???)-任何帮助或指导都将不胜感激。

解决方法

感谢您的评论,这使我想到了解决方案。我发现,此问题与以下事实有关:测试sql文件是在Windows上创建的,因此它们在行尾始终始终带有<CR><LF>字符。这导致了我发布的原始bash脚本中的事实,脚本行

while read script_line

不仅将行中的给定文件名放入变量中,还将字符@@

@@a.sql

还有<CR>字符-则变量中的就是值

@@a.sql<CR>

根本找不到文件a.sql等的原因是什么。当然,该字符是不可见的,因此在我在此处进行的任何调试回显中均未显示该字符-我不得不将$file_name的内容放在其他一些字符之间,然后才能在回显测试中看到它。我还进行了其他一些更正,最终的工作脚本按以下方式显示,如果有人需要将引用的SQL脚本合并为一个,则可以这样做:

#!/bin/bash
#
#
function err () {
    echo $* > "/dev/stderr"
}


function replace_subscripts_placeholders() {
    local PROCESSING_FILENAME=$1
    echo "-- processing file $PROCESSING_FILENAME"
    while read script_line || [ -n "$script_line" ]; do
        local script_line_NO_LEAD_SPACE="$(echo -e "${script_line}" | sed -e 's/^[[:space:]]*//' | sed -e 's/^M$//')"
        if  [[ $script_line_NO_LEAD_SPACE == \@\@* ]] ; then
            local file_name="${script_line_NO_LEAD_SPACE#\@\@}"
            echo "-- found reference to file $file_name"
            if [ -f "$file_name" ]; then
                replace_subscripts_placeholders $file_name
            else
                err_msg="WARNING: Could not find the referenced file $file_name"
                echo "-- $err_msg"
                err $err_msg
            fi          
        else
            echo "$script_line"
        fi
    done < $PROCESSING_FILENAME 
}

if test -z "$1" ; then
    err "Usage: oracle-script-compressor.sh {file_name_to_process} [> output_file]"
    err "  Be aware,if the referenced files within {file_name_to_process} are not specified by absolute paths,you have to start the script from corresponding directory."
    err "  If the part [> output_file] is omitted,then this script writes to standard output"
    err "  If the part [>> output_file] is used,then the result will be appended to output_file it it exists before the processing"
else
    if [ -f "$1" ]; then
        replace_subscripts_placeholders $1
    else
        echo "file $1 does not exist"
    fi
fi

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?