【问题标题】:How to check if a user-specified name refers to a directory or not?如何检查用户指定的名称是否引用目录?
【发布时间】:2017-02-06 02:30:20
【问题描述】:

我正在尝试编写一个简单的程序来检查给定的文件名是否引用了一个目录。但是当我运行 ./isdir.sh (这是脚本的名称)时,我不断收到错误消息说“错误的解释器:没有这样的文件或目录”。

这是我的代码:

#!bin/sh

if [[ $# -ne 1 ]];then
    echo "Usage: $0 dir"
    exit 1
fi

dir="$1"
dirname = "$1"

if [[ ! -d "$dir" ]]; then
    echo "Error: directory $dir not found."
    exit 2
fi

if [[ -d "$dirname" ]]; then
    echo "$dirname is a directory."
    exit 3

另外,重要的问题: 如何处理其中包含空格的输入值?

【问题讨论】:

  • 第一行可能应该是#!/bin/sh(缺少斜线),或者更好的是#!/bin/bash,因为[[ ]] 构造只在Bash 中有效。
  • 要添加到 @BenjaminW. 的有用评论:虽然它不会发现 shebang-line 问题(#!bin/sh 而不是 #!/bin/sh),但将您的代码粘贴到 shellcheck.net 会揭示了[[ 问题等等。

标签: linux bash shell


【解决方案1】:

你可以这样做:

#!/bin/bash

if [[ $# -ne 1 ]]; then
  echo "Usage: $0 dir"
  exit 2
fi

dir="$1"
rc=1
if [[ -d "$dir" ]]; then
  # it is a directory
  rc=0
elif [[ -e "$dir" ]]; then
  echo "Error: '$dir' is not a directory"
else 
  echo "Error: directory '$dir' does not exist"
fi

exit "$rc"

  • 不需要dirname 变量。
  • 该脚本对于名称中包含空格或通配符的目录是安全的,因为我们已将变量括在双引号中。
  • 退出代码 2 是无效参数错误的 Unix 标准;退出 1 是所有其他错误。但是,您可以根据需要更改退出代码。

有关此问题的更多观点,请参阅此相关帖子:Check if a directory exists in a shell script

【讨论】:

  • #!/bin/sh 可能是 Bash 以外的 shell,并且不支持 [[ ]]。即使是 Bash,它也是以 POSIX 模式启动的,可能会产生很多不希望的副作用。在我的机器上,当我使用 sh 运行 Bash 时,甚至无法识别 [[ ]]
  • 我已经更新了我的答案,以便脚本使用 Bash。
  • @codeforester 您可能想要删除“用 sh 测试并且它有效。”根据您的回答,因为这取决于对 [[ ]] 测试的 shell 理解,即 Bash。或者你可以使用[ ] 测试,我认为它可以在这里工作。
  • 它确实可以在我的 Mac 上使用 sh。我已经更新了答案以避免任何混淆。
  • Re "它确实与我的 Mac 上的 sh 一起工作": on macOS, bash` 充当 sh,即使当作为 sh 调用时,它也会将其行为更改为符合 POSIX,它仍然留下了许多非标准的扩展——比如启用了[[ … ]],这使得它成为测试可移植脚本的糟糕环境。关键是:为了可移植,你不能使用任何超出POSIX spec 规定的功能。其中现代 shell,dash - 在 Ubuntu 系统上充当 sh - 最接近支持 POSIX 功能。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-05
  • 1970-01-01
  • 2020-08-09
  • 2012-01-12
相关资源
最近更新 更多