如何在路径中展开波浪号(~)

13 浏览
0 Comments

如何在路径中展开波浪号(~)

我有一个shell脚本,从用户那里获取目录路径,但我需要检查目录是否为空。如果用户使用~而不是绝对路径来输入自己的主目录路径,那么我无法使用ls来检查它。\n

  echo "请指定您的项目根目录。例如:~/Base/project1"
  read directory
  if [ ! -z "$directory" ]
  then
    if [ "$(ls -A "$directory")" ]
    then
      echo 目录 $directory 不为空
    else
      echo 目录 $directory 为空(或不存在)
    fi
    directory="$directory"
  else
    echo "未指定根目录。正在退出..."
    exit;
  fi

\n我遇到了错误:ls无法读取带有~的路径,如何在检查目录是否为空之前展开它?

0
0 Comments

如何在路径中扩展波浪号(~)

问题原因:

在shell中,波浪号(~)通常用来表示用户的主目录。然而,在某些情况下,我们需要在路径中扩展波浪号,以获取完整的路径。但是,直接在shell中使用波浪号进行路径扩展可能存在安全风险,因为它可能会执行恶意代码或导致意外效果。

解决方法一:

我们可以使用eval命令来让shell帮助我们解释和扩展路径表达式。通过eval命令,我们可以安全地将路径中的波浪号进行扩展。以下是使用eval命令的示例代码:

eval directory="$directory"

解决方法二:

在POSIX环境下,我们还可以使用C语言编写一个简单的程序来扩展路径中的波浪号。以下是一个示例程序tildeexp.c的代码:

#include 
#include 
#include 
int main(int argc, char **argv)
{
  wordexp_t p;
  int rc;
  rc = wordexp(argv[1], &p, 0);
  if (rc) {
    fprintf(stderr, "Failed to expand %s: %d\n",
        argv[1], rc);
  } else {
    printf("%s\n", p.we_wordc ? p.we_wordv[0] : "");
  }
  wordfree(&p);
  return (rc ? 1 : 0);
}

我们可以使用gcc编译器将该程序编译为可执行文件:

gcc -Wall -g -O2 -o tildeexp tildeexp.c

然后,我们可以在shell脚本中使用该程序来扩展路径:

directory=$(/path/to/tildeexp "$directory")
if [ $? -eq 0 ]; then
  # 扩展成功
else
  # 扩展失败
fi

解决方法三:

另一种解决方法是使用Perl的glob函数来扩展路径中的波浪号。以下是使用Perl的示例代码:

directory="${directory//$"'"/$"\\'"}"
directory=$(perl -e "print glob('$directory')")

这种方法也能正常工作,但需要注意的是,如果路径中包含像$(ls)这样的命令执行语句,那么这个方法可能存在安全风险,因为它可能导致命令注入或提升特权漏洞。

我们可以使用eval命令、编写C程序或使用Perl的glob函数来扩展路径中的波浪号。这些方法可以帮助我们安全地获取完整的路径。

0
0 Comments

在路径中展开波浪线(~)的方法

当我们在使用shell脚本时,有时候会遇到需要展开路径中的波浪线(~)的情况。波浪线通常用于表示用户的家目录。然而,在某些情况下,shell并不会自动展开波浪线,这就需要我们手动进行展开。

展开波浪线的原因是因为shell会将波浪线视为普通字符,而不会将其解释为用户的家目录。这可能导致路径无法正确解析,从而导致脚本无法正常执行。

为了解决这个问题,我们可以使用不同的方法来展开波浪线。下面是两种常见的解决方法:

方法一:使用eval函数展开波浪线

eval函数可以将字符串作为代码执行。我们可以使用eval来展开包含波浪线的路径。以下是一个示例代码:

if [ "${directory:0:1}" == \~ ]; then
  eval directory="$(printf '~%q' "${directory#\~}")"
fi

这段代码首先判断路径是否以波浪线开头,如果是,则使用printf函数将路径中的特殊字符进行转义,并将转义后的路径赋值给directory变量。然后使用eval函数执行该路径。

方法二:手动展开波浪线

如果shell不支持eval函数,我们可以手动展开波浪线。以下是一个示例代码:

prefix=${directory%%/*}
if [ "$prefix" == \~ ]; then
  # 隐式使用当前用户。
  user=$USER
else
  # 从波浪线前缀中解析用户。
  user=${prefix#\~}
fi
# 获取用户的家目录。只有当展开后的目录存在时才进行展开。
homedir=$(getent passwd -- "$user" | cut -d: -f6)
if [ -d "$homedir" ]; then
  # 用家目录的绝对路径替换波浪线前缀。
  directory=$homedir${directory#$prefix}
fi

这段代码首先检查路径的前缀是否是波浪线。如果是,则隐式使用当前用户;如果不是,则从波浪线前缀中解析出用户。然后使用getent命令获取用户的家目录,并将其赋值给homedir变量。最后,将路径中的波浪线前缀替换为家目录的绝对路径。

通过以上两种方法,我们可以在shell脚本中展开路径中的波浪线,确保脚本能够正确解析路径并执行相应操作。无论是使用eval函数还是手动展开,我们都需要注意安全性,避免用户输入恶意代码或导致副作用的内容。

0