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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20204820/
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-10 00:27:27  来源:igfitidea点击:

Check If Shell Script $1 Is Absolute Or Relative Path

bashshell

提问by Dragos Rizescu

As the title says, I am trying to determine if my bash script receives a full path or a relative file to a directory as a parameter.

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

For some reasons the following doesn't seem to work for me:

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

#!/bin/bash

DIR=

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

When I run my script with either a full path or absolute path it says:

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

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

For some reasons I can't seem to figure this bug. Any ideas?

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

回答by chepner

[ ... ]doesn't do pattern matching. /*is being expanded to the contents of /, so effectively you have

[ ... ]不做模式匹配。/*正在扩展到 的内容/,因此您可以有效地

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

or something similar. Use [[ ... ]]instead.

或类似的东西。使用[[ ... ]]来代替。

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

For POSIX compliance, or if you just don't have a [[that does pattern matching, use a casestatement.

为了符合 POSIX,或者如果您[[没有进行模式匹配的 ,请使用case语句。

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

回答by thom

Just test on the first character:

只需测试第一个字符:

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

回答by David Tonhofer

Writing tests is fun:

编写测试很有趣:

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

回答by loshad vtapkah

One more case is paths started from ~(tilde). ~user/some.fileor ~/some.fileare some kind of absolute paths.

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

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

回答by that other guy

ShellCheckautomatically points out that "[ .. ] can't match globs. Use [[ .. ]] or grep."

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

In other words, use

换句话说,使用

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

This is because [is a regular command, so /*is expanded by the shell beforehand, turning it into

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

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

[[is handled specially by the shell, and doesn't have this problem.

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