在 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 上,我们如何测试名称字符串是否可执行?
你的逻辑type
shell 内置命令应该可以工作(排除 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"