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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4665051/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 20:04:13  来源:igfitidea点击:

Check if passed argument is file or directory in Bash

bashshell

提问by Andy

I'm trying to write an extremely simple script in Ubuntu which would allow me to pass it either a filename or a directory, and be able to do something specific when it's a file, and something else when it's a directory. The problem I'm having is when the directory name, or probably files too, has spaces or other escapable characters are in the name.

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

Here's my basic code down below, and a couple tests.

下面是我的基本代码,以及一些测试。

#!/bin/bash

PASSED=

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

And here's the output:

这是输出:

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

All of those paths are valid, and exist.

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

回答by John Kugelman

That should work. I am not sure why it's failing. You're quoting your variables properly. What happens if you use this script with double [[]]?

那应该工作。我不确定为什么它失败了。您正确引用了变量。如果将此脚本与 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

Double square brackets is a bash extension to [ ]. It doesn't require variables to be quoted, not even if they contain spaces.

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

Also worth trying: -eto test if a path exists without testing what type of file it is.

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

回答by Jonathan Leffler

At least write the code without the bushy tree:

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

#!/bin/bash

PASSED=

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

When I put that into a file "xx.sh" and create a file "xx sh", and run it, I get:

当我将它放入文件“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
$

Given that you are having problems, you should debug the script by adding:

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

ls -l "${PASSED}"

This will show you what lsthinks about the names you pass the script.

这将显示您对ls传递脚本的名称有何看法。

回答by Mike Q

Using the "file" command may be useful for this:

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

#!/bin/bash
check_file(){

if [ -z "" ] ;then
 echo "Please input something"
 return;
fi

f=""
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 ""

Output examples :

输出示例:

$ ./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) 

FYI: the answers above work but you can use -s to help in weird situations by checking for a valid file first:

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

#!/bin/bash

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

check_file 

回答by Kamran

Using -fand -dswitches on /bin/test:

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

F_NAME=""

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

回答by Jaison John

A more elegant solution

更优雅的解决方案

echo "Enter the file name"
read x
if [ -f $x ]
then
    echo "This is a regular file"
else
    echo "This is a directory"
fi

回答by u10899423

function check_file_path(){
    [ -f "" ] && return
    [ -d "" ] && return
    return 1
}
check_file_path $path_or_file

回答by user11791326

This shhould work:

这应该有效:

#!/bin/bash

echo "Enter your Path:"
read a

if [[ -d $a ]]; then 
    echo "$a is a Dir" 
elif [[ -f $a ]]; then 
    echo "$a is the File" 
else 
    echo "Invalid path" 
fi

回答by noelmcloughlin

One liner

一个班轮

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

result is true (0)(dir) or true (0)(file) or false (1)(neither)

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

回答by muj

#!/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