检查Shell脚本$ 1是绝对路径还是相对路径

Dra*_*scu 21 bash shell

正如标题所说,我正在尝试确定我的bash脚本是否将完整路径或相关文件作为参数接收到目录.

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

#!/bin/bash

DIR=$1

if [ "$DIR" = /* ]
then
    echo "absolute"
else
    echo "relative"
fi
Run Code Online (Sandbox Code Playgroud)

当我用完整路径或绝对路径运行我的脚本时,它说:

./script.sh: line 5: [: too many arguments
relative
Run Code Online (Sandbox Code Playgroud)

由于某些原因,我似乎无法弄清楚这个错误.有任何想法吗?

che*_*ner 36

[ ... ]不进行模式匹配./*正在扩展到内容/,所以你有效

if [ "$DIR" = /bin /boot /dev /etc /home /lib /media ... /usr /var ]
Run Code Online (Sandbox Code Playgroud)

或类似的东西.请[[ ... ]]改用.

if [[ "$DIR" = /* ]]; then
Run Code Online (Sandbox Code Playgroud)

对于POSIX合规性,或者如果您[[没有进行模式匹配,请使用case语句.

case $DIR in
  /*) echo "absolute path" ;;
  *) echo "something else" ;;
esac
Run Code Online (Sandbox Code Playgroud)

  • 相对路径是指引用不同文件的路径,具体取决于当前工作目录的内容.该路径始终引用`/ home/user/folder2`,因此它是绝对路径.`..`不仅仅是一个shell快捷方式; 它是文件系统中一个非常真实的条目,用于包含它的目录的父目录. (14认同)

tho*_*hom 23

只测试第一个字符:

if [ "${DIR:0:1}" = "/" ]
Run Code Online (Sandbox Code Playgroud)

  • 适用于`bash`(以及`ksh`和`zsh`),但为了避免可能的混淆:尽管使用了`[...]`和`=`,这个解决方案不符合POSIX(POSIX) shell spec.不支持位置子串提取).如果POSIX符合性不是必需的,就像在这种情况下一样,通常最好使用`[[...]]`:`[["$ {DIR:0:1}"=='/']]`(甚至`[[$ {DIR:0:1} =='/']]`). (4认同)

los*_*kah 7

另一种情况是从~(波浪号)开始的路径。~user/some.file或者~/some.file是某种绝对路径。

if [[ "${dir:0:1}" == / || "${dir:0:2}" == ~[/a-z] ]]
then
    echo "Absolute"
else
    echo "Relative"
fi
Run Code Online (Sandbox Code Playgroud)


tha*_*guy 5

ShellCheck自动指出“ [ .. ] can't match globs. Use [[ .. ]] or grep.”

换句话说,使用

if [[ "$DIR" = /* ]]
Run Code Online (Sandbox Code Playgroud)

这是因为[是一个普通命令,所以/*事先被shell展开,变成了

[ "$DIR" = /bin /dev /etc /home .. ]
Run Code Online (Sandbox Code Playgroud)

[[ 由shell专门处理,没有这个问题。


Dav*_*fer 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
Run Code Online (Sandbox Code Playgroud)