Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Shell 如何确定命令是否以符合POSIX的方式存在?_Shell_Posix - Fatal编程技术网

Shell 如何确定命令是否以符合POSIX的方式存在?

Shell 如何确定命令是否以符合POSIX的方式存在?,shell,posix,Shell,Posix,请参阅上的讨论。它描述了type以及command-v选项在中是可选的 标有“正确”的答案也没用。与类型一样,散列在POSIX.1-2004中也标记为XSI。看 那么,编写shell脚本以查找系统上是否存在命令的POSIX兼容方式是什么呢?您希望如何进行?您可以在当前值为$PATH的目录中查找该命令;您可以在默认情况下指定的目录中查找系统路径(getconf PATH),只要 存在于路径上) 您将使用哪种实现语言?(例如:我有一个Perl实现,它可以在$PATH上找到可执行文件,但Perl不是P

请参阅上的讨论。它描述了
type
以及
command-v
选项在中是可选的

标有“正确”的答案也没用。与
类型
一样,
散列
在POSIX.1-2004中也标记为XSI。看


那么,编写shell脚本以查找系统上是否存在命令的POSIX兼容方式是什么呢?

您希望如何进行?您可以在当前值为
$PATH
的目录中查找该命令;您可以在默认情况下指定的目录中查找系统路径(
getconf PATH
),只要 存在于路径上)

您将使用哪种实现语言?(例如:我有一个Perl实现,它可以在
$PATH
上找到可执行文件,但Perl不是POSIX的一部分;它与您有远程关系吗?)

为什么不试着运行它呢?如果您要处理基于脚本的系统,很多可执行文件都无法通过搜索找到,它们内置在shell中。主要的警告是,如果一个命令在没有参数的情况下运行时发生了危险的事情——但是很少有POSIX命令(如果有的话)会这样做。您可能还需要确定哪些命令退出状态指示找不到该命令,而哪些命令反对不使用适当的参数调用。而且几乎不能保证所有系统在这方面都是一致的。这是一个令人担忧的过程,以防你没有收集

Perl实现
pathfile
#/usr/bin/env perl
#
#@(#)$Id:pathfile.pl,v3.4 2015/10/16 19:39:23 jleffler Exp$
#
#执行哪个命令
#松散地基于Kernighan&Pike“UNIX编程环境”中的“which”
#使用v5.10.0;#使用//定义或运算符;不是在Perl 5.8.x中
严格使用;
使用警告;
使用Getopt::Std;
使用Cwd“realpath”;
使用File::Basename;
我的$arg0=basename($0,'.pl');
my$usestr=“用法:$arg0[-AafhqrsVwx][-p path]命令…\n”;

my$hlpstr=您希望如何进行?您可以在当前值为
$PATH
的目录中查找该命令;您可以在默认情况下指定的目录中查找系统路径(
getconf PATH
——只要路径上存在
getconf
)。您将使用哪种实现语言?(例如:我有一个Perl实现——但Perl不是POSIX的一部分;它与您有远程关系吗?)为什么不试着运行它呢?如果您要处理基于Busybox的系统,很多可执行文件都无法通过搜索找到——它们内置在shell中。尝试简单地运行它听起来是个不错的方法。如果你能把它作为一个答案贴出来,我会接受它并结束这个问题。@LoneLearner:可能是2004年没有符合posix标准的方法来做这件事,也许这就是他们制作-V的原因mandatory@ChrisBeck
hash
不是必需的,就像posixshell中的
type
不是必需的一样。请参阅概要中的
XSI
边距代码:。@LoneLearner:是的,您是对的,它不是重复的,所以为什么不使用
哪个
命令来确定路径;如果path下不存在这样的路径,它将输出null,对吗?@jamo我们知道
哪个
做什么,但这个问题是关于一个解决方案的,该解决方案可以在任何符合POSIX的系统和符合POSIX的shell上工作。中未定义
命令的
#!/usr/bin/env perl
#
# @(#)$Id: pathfile.pl,v 3.4 2015/10/16 19:39:23 jleffler Exp $
#
# Which command is executed

# Loosely based on 'which' from Kernighan & Pike "The UNIX Programming Environment"

#use v5.10.0;    # Uses // defined-or operator; not in Perl 5.8.x
use strict;
use warnings;
use Getopt::Std;
use Cwd 'realpath';
use File::Basename;

my $arg0 = basename($0, '.pl');
my $usestr = "Usage: $arg0 [-AafhqrsVwx] [-p path] command ...\n";
my $hlpstr = <<EOS;

  -A       Absolute pathname (determined by realpath)
  -a       Print all possible matches
  -f       Print names of files (as opposed to symlinks, directories, etc)
  -h       Print this help message and exit
  -q       Quiet mode (don't print messages about files not found)
  -r       Print names of files that are readable
  -s       Print names of files that are not empty
  -V       Print version information and exit
  -w       Print names of files that are writable
  -x       Print names of files that are executable
  -p path  Use PATH
EOS

sub usage
{
    print STDERR $usestr;
    exit 1;
}

sub help
{
    print $usestr;
    print $hlpstr;
    exit 0;
}

sub version
{
    my $version = 'PATHFILE Version $Revision: 3.4 $ ($Date: 2015/10/16 19:39:23 $)';
    # Beware of RCS hacking at RCS keywords!
    # Convert date field to ISO 8601 (ISO 9075) notation
    $version =~ s%\$(Date:) (\d\d\d\d)/(\d\d)/(\d\d) (\d\d:\d\d:\d\d) \$%\$$1 $2-$3-$4 $5 \$%go;
    # Remove keywords
    $version =~ s/\$([A-Z][a-z]+|RCSfile): ([^\$]+) \$/$2/go;
    print "$version\n";
    exit 0;
}

my %opts;
usage   unless getopts('AafhqrsVwxp:', \%opts);
version if ($opts{V});
help    if ($opts{h});
usage   unless scalar(@ARGV);

# Establish test and generate test subroutine.
my $chk = 0;
my $test = "-x";
my $optlist = "";
foreach my $opt ('f', 'r', 's', 'w', 'x')
{
    if ($opts{$opt})
    {
        $chk++;
        $test = "-$opt";
        $optlist .= " -$opt";
    }
}
if ($chk > 1)
{
    $optlist =~ s/^ //;
    $optlist =~ s/ /, /g;
    print STDERR "$arg0: mutually exclusive arguments ($optlist) given\n";
    usage;
}
my $chk_ref = eval "sub { my(\$cmd) = \@_; return -f \$cmd && $test \$cmd; }";

my @PATHDIRS;
my %pathdirs;
my $path = defined($opts{p}) ? $opts{p} : $ENV{PATH};
#foreach my $element (split /:/, $opts{p} // $ENV{PATH})
foreach my $element (split /:/, $path)
{
    $element = "." if $element eq "";
    push @PATHDIRS, $element if $pathdirs{$element}++ == 0;
}

my $estat = 0;
CMD:
foreach my $cmd (@ARGV)
{
    if ($cmd =~ m%/%)
    {
        if (&$chk_ref($cmd))
        {
            print "$cmd\n" unless $opts{q};
            next CMD;
        }
        print STDERR "$arg0: $cmd: not found\n" unless $opts{q};
        $estat = 1;
    }
    else
    {
        my $found = 0;
        foreach my $directory (@PATHDIRS)
        {
            my $file = "$directory/$cmd";
            if (&$chk_ref($file))
            {
                $file = realpath($file) if $opts{A};
                print "$file\n" unless $opts{q};
                next CMD unless defined($opts{a});
                $found = 1;
            }
        }
        print STDERR "$arg0: $cmd: not found\n" unless $found || $opts{q};
        $estat = 1;
    }
}

exit $estat;