检查传递的参数是否是Bash中的文件或目录

And*_*ndy 135 bash shell

我正在尝试在Ubuntu中编写一个非常简单的脚本,它允许我传递文件名或目录,并且能够在它是文件时执行特定的操作,而当它是目录时则执行其他操作.我遇到的问题是目录名称,或者也可能是文件,名称中包含空格或其他可以逃避的字符.

这是我下面的基本代码,以及几个测试.

#!/bin/bash

PASSED=$1

if [ -d "${PASSED}" ] ; then
    echo "$PASSED is a directory";
else
    if [ -f "${PASSED}" ]; then
        echo "${PASSED} is a file";
    else
        echo "${PASSED} is not valid";
        exit 1
    fi
fi
Run Code Online (Sandbox Code Playgroud)

这是输出:

andy@server~ $ ./scripts/testmove.sh /home/andy/
/home/andy/ is a directory

andy@server~ $ ./scripts/testmove.sh /home/andy/blah.txt
/home/andy/blah.txt is a file

andy@server~ $ ./scripts/testmove.sh /home/andy/blah\ with\ a\ space.txt
/home/andy/blah with a space.txt is not valid

andy@server~ $ ./scripts/testmove.sh /home/andy\ with\ a\ space/
/home/andy with a space/ is not valid
Run Code Online (Sandbox Code Playgroud)

所有这些路径都是有效的,并且存在.

Joh*_*ica 182

这应该工作.我不知道为什么会失败.你正确地引用你的变量.如果您将此脚本与double一起使用会发生什么[[ ]]

if [[ -d $PASSED ]]; then
    echo "$PASSED is a directory"
elif [[ -f $PASSED ]]; then
    echo "$PASSED is a file"
else
    echo "$PASSED is not valid"
    exit 1
fi
Run Code Online (Sandbox Code Playgroud)

双方括号是bash扩展名[ ].它不需要引用变量,即使它们包含空格也不需要.

另外值得尝试:-e测试路径是否存在而不测试它是什么类型的文件.


Jon*_*ler 9

至少在没有浓密树的情况下编写代码:

#!/bin/bash

PASSED=$1

if   [ -d "${PASSED}" ]
then echo "${PASSED} is a directory";
elif [ -f "${PASSED}" ]
then echo "${PASSED} is a file";
else echo "${PASSED} is not valid";
     exit 1
fi
Run Code Online (Sandbox Code Playgroud)

当我把它放入文件"xx.sh"并创建一个文件"xx sh",然后运行它,我得到:

$ cp /dev/null "xx sh"
$ for file in . xx*; do sh "$file"; done
. is a directory
xx sh is a file
xx.sh is a file
$
Run Code Online (Sandbox Code Playgroud)

鉴于您遇到问题,您应该通过添加以下内容来调试脚本:

ls -l "${PASSED}"
Run Code Online (Sandbox Code Playgroud)

这将显示您对ls通过脚本的名称的看法.


Kam*_*ran 6

使用-f-d开启/bin/test

F_NAME="${1}"

if test -f "${F_NAME}"
then                                   
   echo "${F_NAME} is a file"
elif test -d "${F_NAME}"
then
   echo "${F_NAME} is a directory"
else                                   
   echo "${F_NAME} is not valid"
fi
Run Code Online (Sandbox Code Playgroud)

  • 一般来说,当已有等效答案时,您不应该费心为旧问题添加新答案。如果您有一些令人震惊的新信息要添加,但无论如何都要给出答案。但你所说的已经说过了。(“test”通常是内置的 shell,尽管通常还有一个可执行文件,例如“/bin/test”和“/bin/[”。) (2认同)

Mik*_*e Q 5

使用“file”命令可能对此有用:

#!/bin/bash
check_file(){

if [ -z "${1}" ] ;then
 echo "Please input something"
 return;
fi

f="${1}"
result="$(file $f)"
if [[ $result == *"cannot open"* ]] ;then
        echo "NO FILE FOUND ($result) ";
elif [[ $result == *"directory"* ]] ;then
        echo "DIRECTORY FOUND ($result) ";
else
        echo "FILE FOUND ($result) ";
fi

}

check_file "${1}"
Run Code Online (Sandbox Code Playgroud)

输出示例:

$ ./f.bash login
DIRECTORY FOUND (login: directory) 
$ ./f.bash ldasdas
NO FILE FOUND (ldasdas: cannot open `ldasdas' (No such file or  directory)) 
$ ./f.bash evil.php 
FILE FOUND (evil.php: PHP script, ASCII text) 
Run Code Online (Sandbox Code Playgroud)

仅供参考:上面的答案有效,但您可以使用 -s 通过首先检查有效文件来帮助解决奇怪的情况:

#!/bin/bash

check_file(){
    local file="${1}"
    [[ -s "${file}" ]] || { echo "is not valid"; return; } 
    [[ -d "${file}" ]] && { echo "is a directory"; return; }
    [[ -f "${file}" ]] && { echo "is a file"; return; }
}

check_file ${1}
Run Code Online (Sandbox Code Playgroud)