检查文件是否存在[BASH]

时间:2014-03-28 18:01:28

标签: bash shell

如何检查bash中是否存在文件?

当我尝试这样做时:

FILE1="${@:$OPTIND:1}"
if [ ! -e "$FILE1" ]
then 
    echo "requested file doesn't exist" >&2
    exit 1
elif
<more code follows>

我总是得到以下输出:

 requested file doesn't exist

程序使用如下:

script.sh [-g] [-p] [-r FUNCTION_ID|-d FUNCTION_ID] FILE

有什么想法吗? 我会很高兴得到任何帮助。

P.S。我希望我可以展示整个文件,而不会因为复制而被解雇。如果有私密的沟通方式,我很乐意帮忙。

我的错误。 Fas强制二进制文件进入错误的位置。感谢大家的帮助。

4 个答案:

答案 0 :(得分:3)

调试这样的问题的小技巧。将这些行添加到脚本的顶部:

export PS4="\$LINENO: "
set -xv

set -xv将在执行前打印出每一行,然后在shell插入变量等时打印出行。$PS4set -xv使用的提示。这将在执行时打印shell脚本的行号。您将能够了解正在发生的事情以及您可能遇到问题的地方。

以下是测试脚本的示例:

#! /bin/bash

export PS4="\$LINENO: "
set -xv

FILE1="${@:$OPTIND:1}"         # Line 6
if [ ! -e "$FILE1" ]           # Line 7
then 
    echo "requested file doesn't exist" >&2
    exit 1
else
    echo "Found File $FILE1"   # Line 12
fi

这就是我运行时得到的结果:

$ ./test.sh .profile
    FILE1="${@:$OPTIND:1}"
6: FILE1=.profile
    if [ ! -e "$FILE1" ]
    then 
        echo "requested file doesn't exist" >&2
        exit 1
    else
        echo "Found File $FILE1"
    fi
7: [ ! -e .profile ]
12: echo 'Found File .profile'
Found File .profile

在这里,我可以看到我将$FILE1设置为.profile,并且我的脚本理解${@:$OPTIND:1}。关于这一点的最好的事情是它适用于所有shell到原始的Bourne shell。这意味着如果您没有按照自己的想法运行Bash,那么您将看到脚本失败的位置,并可能解决问题。

我怀疑你可能没有在Bash中运行你的脚本。你把#! /bin/bash放在了最前面吗?


  

script.sh [-g] [-p] [-r FUNCTION_ID | -d FUNCTION_ID] FILE

您可能希望使用getopts来解析参数:

#! /bin/bash

USAGE=" Usage:
    script.sh [-g] [-p] [-r FUNCTION_ID|-d FUNCTION_ID] FILE
"
while getopts gpr:d: option
do
    case $option in
        g)  g_opt=1;;
        p)  p_opt=1;;
        r)  rfunction_id="$OPTARG";;
        d)  dfunction_id="$OPTARG";;
        [?])
            echo "Invalid Usage" 1>&2
            echo "$USAGE"        1>&2
            exit 2
            ;;
    esac
done

if [[ -n $rfunction_id && -n $dfunction_id ]]
then
    echo "Invalid Usage: You can't specify both -r and -d" 1>&2
    echo "$USAGE" >2&
    exit 2
fi

shift $(($OPTIND - 1))
[[ -n $g_opt ]] && echo "-g was set"
[[ -n $p_opt ]] && echo "-p was set"
[[ -n $rfunction_id ]] && echo "-r was set to $rfunction_id"
[[ -n $dfunction_id ]] && echo "-d was set to $dfunction_id"
[[ -n $1 ]] && echo "File is $1"

答案 1 :(得分:1)

To(回顾)并添加到@ DavidW。的优秀答案:

  • 检查脚本的shebang行(第一行)以确保它由bash执行:是#!/bin/bash还是#!/usr/bin/env bash

  • 检查脚本文件中是否存在可能导致意外行为的隐藏控制字符(例如\r);运行cat -v scriptFile | fgrep ^ - 它应该产生NO输出;如果该文件包含\r个字符,则会显示为^M

    • 要删除\r个实例(更准确地说,要将Windows风格的\r\n换行序列转换为Unix \n - 仅限序列),您可以使用dos2unix file进行转换到位;如果您没有此实用程序,可以使用sed 's/'$'\r''$//' file > outfile(CAVEAT:使用不同的输出文件,否则您将销毁您的输入文件);要删除所有 \r个实例(即使后面没有\n),请使用tr -d '\r' < file > outfile(CAVEAT:使用不同的输出文件,否则你会破坏你的输入文件)。
  • 除了@ DavidW。优秀的调试技术外,您还可以将以下内容添加到直观检查传递给您脚本的所有参数
i=0; for a; do echo "\$$((i+=1))=[$a]"; done 

(将值括在[...](例如)中的目的是查看值的确切边界。)

这会产生类似的结果:

$1=[-g]
$2=[input.txt]
...

但请注意,如果没有传递任何参数,则不会打印任何内容。

答案 2 :(得分:0)

尝试打印FILE1以查看它是否具有您想要的值,如果不是问题,这是一个简单的脚本(下面的站点):

#!/bin/bash
file="${@:$OPTIND:1}"
if [ -f "$file" ]
then
    echo "$file found."
else
    echo "$file not found."
fi

http://www.cyberciti.biz/faq/unix-linux-test-existence-of-file-in-bash/

答案 3 :(得分:0)

不是以一种棘手的方式从“$ @”中拔出一个项目,为什么不用shift关闭你用getopts处理过的args:

while getopts ...
done

shift $(( OPTIND - 1 ))

FILE1=$1