如何检查shell脚本$1参数是绝对路径还是相对路径? [重复]

问题描述 投票:0回答:5

如标题所示,我试图确定我的 BASH 脚本是否接收作为参数:完整路径或目录的相对文件。

由于某些原因,以下内容似乎对我不起作用:

#!/bin/bash

DIR=$1

if [ "$DIR" = /* ]
then
    echo "absolute"
else
    echo "relative"
fi

当我使用完整路径或绝对路径运行脚本时,它会显示:

./script.sh: line 5: [: too many arguments
relative

由于某些原因,我似乎无法弄清楚这个错误。有什么想法吗?

bash shell
5个回答
54
投票

[ ... ]
不进行模式匹配。
/*
正在扩展到
/
的内容,因此您实际上已经

if [ "$DIR" = /bin /boot /dev /etc /home /lib /media ... /usr /var ]

或类似的东西。请使用

[[ ... ]]
来代替。

if [[ "$DIR" = /* ]]; then

为了 POSIX 合规性,或者如果您没有执行模式匹配的

[[
,请使用
case
语句。

case $DIR in
  /*) echo "absolute path" ;;
  *) echo "something else" ;;
esac

36
投票

仅测试第一个字符:

if [ "${DIR:0:1}" = "/" ]

10
投票

还有一种情况是从

~
(波形符)开始的路径。
~user/some.file
~/some.file
是某种绝对路径。

if [[ "${dir:0:1}" == / || "${dir:0:2}" == ~[/a-z] ]]
then
    echo "Absolute"
else
    echo "Relative"
fi

7
投票

ShellCheck自动指出“

[ .. ] can't match globs. Use [[ .. ]] or grep.

换句话说,使用

if [[ "$DIR" = /* ]]

这是因为

[
是常规命令,所以
/*
事先被 shell 扩展,变成

[ "$DIR" = /bin /dev /etc /home .. ]

[[
是shell专门处理的,不存在这个问题。


5
投票

编写测试很有趣:

#!/bin/bash

declare -a MY_ARRAY # declare an indexed array variable

MY_ARRAY[0]="/a/b"
MY_ARRAY[1]="a/b"
MY_ARRAY[2]="/a a/b"
MY_ARRAY[3]="a a/b"
MY_ARRAY[4]="/*"


# Note that 
# 1) quotes around MY_PATH in the [[ ]] test are not needed
# 2) the expanded array expression "${MY_ARRAY[@]}" does need the quotes
#    otherwise paths containing spaces will fall apart into separate elements.
# Nasty, nasty syntax.

echo "Test with == /* (correct, regular expression match according to the Pattern Matching section of the bash man page)"

for MY_PATH in "${MY_ARRAY[@]}"; do
   # This works
   if [[ $MY_PATH == /* ]]; then
      echo "'$MY_PATH' is absolute"
   else
      echo "'$MY_PATH' is relative"
   fi
done

echo "Test with == \"/*\" (wrong, becomes string comparison)"

for MY_PATH in "${MY_ARRAY[@]}"; do
   # This does not work at all; comparison with the string "/*" occurs!
   if [[ $MY_PATH == "/*" ]]; then
      echo "'$MY_PATH' is absolute"
   else
      echo "'$MY_PATH' is relative"
   fi
done

echo "Test with = /* (also correct, same as ==)"

for MY_PATH in "${MY_ARRAY[@]}"; do
   if [[ $MY_PATH = /* ]]; then
      echo "'$MY_PATH' is absolute"
   else
      echo "'$MY_PATH' is relative"
   fi
done

echo "Test with =~ /.* (pattern matching according to the regex(7) page)"

# Again, do not quote the regex; '^/' would do too

for MY_PATH in "${MY_ARRAY[@]}"; do
   if [[ $MY_PATH =~ ^/[:print:]* ]]; then
      echo "'$MY_PATH' is absolute"
   else
      echo "'$MY_PATH' is relative"
   fi
done
© www.soinside.com 2019 - 2024. All rights reserved.