检查文件是否存在 [BASH]

use*_*750 6 bash shell

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

当我尝试这样做时:

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

我总是得到以下输出:

 requested file doesn't exist
Run Code Online (Sandbox Code Playgroud)

该程序的使用方式如下:

script.sh [-g] [-p] [-r FUNCTION_ID|-d FUNCTION_ID] FILE
Run Code Online (Sandbox Code Playgroud)

有什么想法吗?我将很高兴提供任何帮助。

PS 我希望我可以展示整个文件,而不用担心因为有副本而被学校开除。如果有私人的沟通方式,我会很乐意帮忙。

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

Dav*_* W. 8

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

export PS4="\$LINENO: "
set -xv
Run Code Online (Sandbox Code Playgroud)

set -xv在执行前打印出每一行,然后是 shell 插入变量等后的行。 是$PS4所使用的提示符set -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
Run Code Online (Sandbox Code Playgroud)

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

$ ./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
Run Code Online (Sandbox Code Playgroud)

在这里,我可以看到我设置$FILE1.profile,并且我的脚本理解该${@:$OPTIND:1}。最好的事情是它适用于所有 shell,直到原始的 Bourne shell。这意味着,如果您没有像您想象的那样运行 Bash,您将看到脚本失败的地方,并可能解决问题。

我怀疑您可能没有在 Bash 中运行脚本。你贴#! /bin/bash在上面了吗?


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

您可能想使用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"
Run Code Online (Sandbox Code Playgroud)


mkl*_*nt0 1

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

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

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

    • 要删除\r实例(更准确地说,是将 Windows 样式的\r\n换行序列转换为 Unix\n专用序列),您可以使用就地dos2unix file转换;如果你没有这个实用程序,你可以使用(警告:使用不同的输出文件,否则你会破坏你的输入文件);要删除所有实例(即使后面没有),请使用 (警告:使用不同的输出文件,否则您将破坏输入文件)。sed 's/'$'\r''$//' file > outfile \r\ntr -d '\r' < file > outfile
  • 除了 @DavidW. 出色的调试技术之外,您还可以添加以下内容来直观地检查传递给脚本的所有参数:
i=0; for a; do echo "\$$((i+=1))=[$a]"; done 
Run Code Online (Sandbox Code Playgroud)

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

这将产生类似的结果:

$1=[-g]
$2=[input.txt]
...
Run Code Online (Sandbox Code Playgroud)

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