关于shell:检查传递的参数是bash中的文件还是目录

Check if passed argument is file or directory in Bash

我正在尝试在Ubuntu中编写一个非常简单的脚本,它允许我将文件名或目录传递给它,当它是一个文件时,我可以做一些特定的事情,当它是一个目录时,我可以做一些其他的事情。我遇到的问题是,当目录名,或者可能是文件名中包含空格或者其他可脱离字符时。

下面是我的基本代码和一些测试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/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

输出结果如下:

1
2
3
4
5
6
7
8
9
10
11
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

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


那应该管用。我不知道为什么会失败。你正确地引用了你的变量。如果将此脚本与double [[]]一起使用,会发生什么情况?

1
2
3
4
5
6
7
8
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

双方括号是对[ ]的bash扩展。它不需要引用变量,即使变量包含空格也是如此。

同样值得尝试的是:-e测试路径是否存在,而不测试它是什么类型的文件。


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

1
2
3
4
5
6
7
8
9
10
11
#!/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

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

1
2
3
4
5
6
$ 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
$

考虑到您有问题,应该通过添加以下内容来调试脚本:

1
ls -l"${PASSED}"

这将向您展示ls对您传递脚本的名称的看法。


更优雅的解决方案

1
2
3
4
5
6
7
8
echo"Enter the file name"
read x
if [ -f $x ]
then
    echo"This is a regular file"
else
    echo"This is a directory"
fi


使用-f-d开关打开/bin/test

1
2
3
4
5
6
7
8
9
10
11
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


更新:我被否决了,所以我决定重新写我的答案,谢谢你的反馈。

使用"file"命令可能有助于:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/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}

输出示例:

1
2
3
4
5
6
$ ./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)

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

1
2
3
4
5
6
7
8
9
10
#!/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}


一班轮

1
touch bob; test -d bob && echo 'dir' || (test -f bob && echo 'file')

结果为真(0)(dir)或真(0)(file)或假(1)(两者都不是)


1
2
3
4
5
6
7
8
9
#!/bin/bash                                                                                              
echo"Please Enter a file name :"                                                                          
read filename                                                                                            
if test -f $filename                                                                                      
then                                                                                                      
        echo"this is a file"                                                                            
else                                                                                                      
        echo"this is not a file"                                                                        
fi