如何在 Bash 中测试名称/字符串是否可执行

如何在 Bash 中测试名称/字符串是否可执行

在 Bash 上,我们如何测试名称字符串是否为可执行文件,因为尝试过它不起作用:

$ [[ -x cp ]] &&echo YES
$
$ [[ -x ls ]] &&echo YES

因为尝试过后发现方法不正确:

$ >/dev/null type ls && echo YES
YES

$ >/dev/null type -fat && echo YES
YES

这是非常失败感谢之前的帮助

答案1

问题不太清楚:

  • 您想测试某个字符串是否对应于可执行命令吗?或者
  • 你想测试一个文件是否可执行

你想测试一个文件是否可执行

-x测试在第二种情况下很有用,因为它测试给定的文件是否可执行,即是否设置了可执行位。

它要求您提供有效的文件名。除非您提供完整的文件路径,否则将搜索当前目录。因此,cp除非您先将可执行文件的目录设为当前目录(即),否则您的命令通常会失败cd /usr/bin

要检索可执行文件的完整文件路径,您可以使用 shell 内置type选项,-P这样只会检索搜索中匹配的可执行文件PATH(忽略别名、散列命令和函数)。请注意,这可能不是系统默认执行的内容。

您还可以添加在测试失败时执行的操作。然后您的语句变为:

[[ -x $(type -P cp) ]] && echo YES || echo NO

也可以写成

test -x $(type -P cp) && echo YES || echo NO

你想测试某个字符串是否对应可执行命令

如果您的问题旨在询问如何测试某个命令在您的系统上是否为可执行命令,只需使用type

type ls &>/dev/null && echo YES || echo NO

如果字符串与可执行文件不对应,Type 将返回错误代码,因此第二个命令将不会被执行。

答案2

您可以使用以下command -v命令来测试这一点:

command -v cp >/dev/null 2>&1 && echo "YES"

将返回:

YES

尽管:

command -v fhdjskfsfs >/dev/null 2>&1 && echo "YES"

很可能不会返回任何内容(除非您在名为的路径中有一个可执行文件fhdjskfsfs)。

答案3

在 Bash 上,我们如何测试名称字符串是否可执行?

你的逻辑typeshell 内置命令应该可以工作(排除 shell 内置命令和函数,因为你似乎想要这样),如果你像这样使用它:

&>/dev/null type -afPt -- ls && echo yes

...只要提供的字符串参数不为空,它就会起作用,否则它将返回0成功) 在一个空字符串上...因此,如果您在脚本中使用它并在变量中传递名称/字符串(例如)var,那么您可能希望像这样使用它:${var:-empty}如果var为空,那么 Bash 会将该变量扩展为单词empty...双引号变量扩展也应该有效。

例子:

$ &>/dev/null type -afPt -- ls && echo yes || echo no
yes
$
$ &>/dev/null type -afPt -- notcommand && echo yes || echo no
no
$
$ &>/dev/null type -afPt -- set && echo yes || echo no
no
$
$ &>/dev/null type -afPt -- ./myscript.sh && echo yes || echo no
yes
$
$ &>/dev/null type -afPt -- echo && echo yes || echo no
yes

注意:如果您要丢弃所有输出,那么您可能不需要所有这些选项,因为只-P应该足以排除 shell 内置命令和函数,因为它强制对传递的字符串中的每个单词进行路径搜索,这将默认排除这两个。

答案4

如果您不仅想测试某个命令是否可执行,还想测试它是什么类型的命令,则可以使用以下 shellscript,您可以为其命名what-about并使其可执行。

#!/bin/bash

LANG=C
inversvid="\0033[7m"
resetvid="\0033[0m"

if [ $# -ne 1 ]
then
 echo "Usage: ${0##*/} <program-name>"
 echo "Will try to find corresponding package"
 echo "and tell what kind of program it is"
 exit 1
fi
command="$1"

str=;for ((i=1;i<=$(tput cols);i++)) do str="-$str";done
tmp="$command"
first=true
curdir="$(pwd)"
tmq=$(which "$command")
tdr="${tmq%/*}"
tex="${tmq##*/}"
if test -d "$tdr"; then cd "$tdr"; fi
#echo "cwd='$(pwd)' ################# d"

while $first || [ "${tmp:0:1}" == "l" ]
do
 first=false
#echo "tmp=$tmp########################################## d 1.0"
 tmp=${tmp##*-\>\ }
 tmq="$tmp"
#echo "tmp=$tmp########################################## d 1.1"
 tmp="$(ls -l "$(which "$tmp")" 2>/dev/null)"
#echo "tmp=$tmp########################################## d 1.2"
 tdr="${tmq%/*}"
 tex="${tmq##*/}"
 if test -d "$tdr"; then cd "$tdr"; fi
# echo "cwd='$(pwd)' ################# d"
 if [ "$tmp" == "" ]
 then
  tmp=$(ls -l "$tex" 2>/dev/null)
#echo "tmp=$tmp########################################## d 2.1"
  tmp=${tmp##*\ }
#echo "tmp=$tmp########################################## d 2.2"
  if [ "$tmp" == "" ]
  then
   echo "$command is not in PATH"
#   package=$(bash -ic "$command -v 2>&1")
#   echo "package=$package XXXXX 0"
   bash -ic "alias '$command' > /dev/null 2>&1" > /dev/null 2>&1
   if [ $? -ne 0 ]
   then
    echo 'looking for package ...'
    package=$(bash -ic "$command -v 2>&1"| sed -e '0,/with:/d'| grep -v '^$')
   else
    echo 'alias, hence not looking for package'
   fi
#   echo "package=$package XXXXX 1"
   if [ "$package" != "" ]
   then
    echo "$str"
    echo "package: [to get command '$1']"
    echo -e "${inversvid}${package}${resetvid}"
   fi
   else
    echo "$tmp"
   fi
 else
  echo "$tmp"
 fi
done
tmp=${tmp##*\ }
if [ "$tmp" != "" ]
then
 echo "$str"
 program="$tex"
 program="$(pwd)/$tex"
 file "$program"
 if [ "$program" == "/usr/bin/snap" ]
 then
  echo "$str"
  echo "/usr/bin/snap run $command     # run $command "
  sprog=$(find /snap/"$command" -type f -iname "$command" \
   -exec file {} \; 2>/dev/null | sort | tail -n1)
  echo -e "${inversvid}file: $sprog$resetvid"
  echo "/usr/bin/snap list $command    # list $command"
  slist="$(/usr/bin/snap list "$command")"
  echo -e "${inversvid}$slist$resetvid"
 else
  package=$(dpkg -S "$program")
  if [ "$package" == "" ]
  then
   package=$(dpkg -S "$tex" | grep -e " /bin/$tex$" -e " /sbin/$tex$")
   if [ "$package" != "" ]
   then
    ls -l /bin /sbin
   fi
  fi
  if [ "$package" != "" ]
  then
   echo "$str"
   echo " package: /path/program  [for command '$1']"
   echo -e "${inversvid} $package ${resetvid}"
  fi
 fi
fi
echo "$str"
alias=$(bash -ic "alias '$command' 2>/dev/null"| grep "$command")
if [ "$alias" != "" ]
then
 echo "$alias"
else
 type=$(bash -ic "type \"$command\" 2>/dev/null")
 if [ "$type" != "" ]
 then
  echo "type: $type"
 elif [ "$alias" == "" ]
 then
  echo "type: $command: not found"
 fi
fi
cd "$curdir"

相关内容