Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash脚本无法识别现有文件_Bash_Oracle_File Exists - Fatal编程技术网

Bash脚本无法识别现有文件

Bash脚本无法识别现有文件,bash,oracle,file-exists,Bash,Oracle,File Exists,我必须编写一个简单的bash脚本,它编译多个sql脚本,这些sql脚本可以包含对其他sql脚本的递归引用,因此最终结果将只有一个sql文件,包含来自所有(可能也是递归的)引用子脚本的所有语句 我创建了一个名为oracle-script-compressor.sh的简单脚本,其中包含以下bash代码: #!/bin/bash # # function err () { echo $* > "/dev/stderr" } function replace_sub

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

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

#!/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
从不进行递归调用,即使我删除了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 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;
-- 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$ 
脚本具有对文件的读取权限,所有内容都在同一文件夹中,我在该文件夹中启动脚本,如果使用当前目录前缀引用该文件,这也无关紧要。“/”有趣的是,脚本开始时的检查正确通过,唯一的问题是函数中的搜索…我还尝试用preferred“”调用函数如果没有它,就没有区别…引用的文件名中也没有尾随空格…如果我将函数中的变量声明为local或not,也没有区别。
所以我不知道,可能是什么问题,也许我只是看了太久,看不到一些东西-似乎它必须是一些琐碎的东西,比如函数是在某个不同的当前目录中启动的-(但是pwd和ls显示目录总是正确的…?)-任何帮助或建议都将不胜感激。

谢谢您的评论,它让我找到了解决方案。我发现,这个问题与以下事实有关:测试sql文件是在Windows上创建的,因此它们在行尾始终包含
字符。这导致了我发布的原始bash脚本中的一个事实,即脚本行

在读取脚本行时

不仅将行中的给定文件名(前面有字符)放入变量中@@

@@a.sql

但是变量中的
字符也是值

@@a.sql

是什么原因导致无法找到文件
a.sql
等。当然,字符是不可见的,因此我在这里进行的任何调试回显中都没有显示它-我必须将
$file\u name
的内容放在一些其他字符之间,然后我可以在回显测试中看到它…我还做了一些其他更正ns和最终的工作脚本如下所示,如果有人需要将引用的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
!/bin/bash
#
#
函数错误(){
echo$*>“/dev/stderr”
}
函数替换\u下标\u占位符(){
本地处理\u文件名=$1
echo”--处理文件$processing\u文件名
在阅读脚本行时,执行以下操作
本地脚本_line_NO_LEAD_SPACE=“$(echo-e“${script\u line}”| sed-e的/^[:SPACE:]*/'| sed-e的/^M$/')”
如果[[$script\u line\u NO\u LEAD\u SPACE==\@\@*];则
本地文件\u name=“${script\u line\u NO\u LEAD\u SPACE\35; \@}”
echo”--找到对文件$file\u name的引用
如果[-f“$file_name”];则
替换\u下标\u占位符$file\u name
其他的
err\u msg=“警告:找不到引用的文件$file\u名称”
echo“-$err_msg”
err$err\u msg
fi
其他的
回显“$script\u行”
fi
完成<$PROCESSING\u文件名
}
如果测试-z“$1”;则
错误“用法:oracle-script-compressor.sh{file_name_to_process}[>output_file]”
err“请注意,如果{file_name_to_process}中引用的文件不是由绝对路径指定的,则必须从相应的目录启动脚本。”
err“如果省略了部件[>output_file],则此脚本将写入标准输出”
err“如果使用部件[>>输出文件],则结果将附加到处理前存在的输出文件”
其他的
如果[-f“$1”];则
替换\u下标\u占位符$1
其他的
echo“文件$1不存在”
fi
fi

欢迎,你应该阅读,更重要的是。我不知道
if
测试(正如@Nic3500所说,你真的需要删掉所有与问题无关的内容——这对于除你之外的其他人来说是一个大而复杂的调试过程),但我确实看到了另一个问题:不要使用
命令来运行函数,它不是这样做的。
命令从当前shell中内联的脚本文件中运行命令(与
源代码
命令非常类似)。我还建议将
set-x
放在问题部分之前,以获取shell在那里执行的执行跟踪。@GordonDavisson Thanx作为答复-
只是绝望的表达:-)。当然,我以前也尝试过,但没有它,它没有任何影响。一般来说,我的道歉-我认为,这个例子是最低限度的:-)冗长是由调试消息引起的,这些消息对代码不重要,但如果重现问题,可能会有所帮助-我想,每个想复制它的人都会以类似的方式进行。但是非常感谢你的提示,我会试试看
#!/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