/*
@(#)File: $RCSfile: not.c,v $
@(#)Version: $Revision: 4.2 $
@(#)Last changed: $Date: 2005/06/22 19:44:07 $
@(#)Purpose: Invert success/failure status of command
@(#)Author: J Leffler
@(#)Copyright: (C) JLSS 1991,1997,2005
*/
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "stderr.h"
#ifndef lint
static const char sccs[] = "@(#)$Id: not.c,v 4.2 2005/06/22 19:44:07 jleffler Exp $";
#endif
int main(int argc, char **argv)
{
int pid;
int corpse;
int status;
err_setarg0(argv[0]);
if (argc <= 1)
{
/* Nothing to execute. Nothing executed successfully. */
/* Inverted exit condition is non-zero */
exit(1);
}
if ((pid = fork()) < 0)
err_syserr("failed to fork\n");
if (pid == 0)
{
/* Child: execute command using PATH etc. */
execvp(argv[1], &argv[1]);
err_syserr("failed to execute command %s\n", argv[1]);
/* NOTREACHED */
}
/* Parent */
while ((corpse = wait(&status)) > 0)
{
if (corpse == pid)
{
/* Status contains exit status of child. */
/* If exit status of child is zero, it succeeded, and we should
exit with a non-zero status */
/* If exit status of child is non-zero, if failed and we should
exit with zero status */
exit(status == 0);
/* NOTREACHED */
}
}
/* Failed to receive notification of child's death -- assume it failed */
return (0);
}
ls nonexistingpath; test $? -eq 2 && echo "yes, nonexistingpath doesn't exist."
# Alternatively without an error message and handling of any error code > 0
ls nonexistingpath 2>/dev/null; test $? -gt 0 && echo "yes, nonexistingpath doesn't exist."
7条答案
按热度按时间e0uiprwp1#
POSIX Shell包含
!
运算符我最近(2015年9月)注意到POSIX shell支持
!
运算符。例如,它被列为保留字,可以出现在管道的开始处-其中简单命令是“管道”的特殊情况。因此,它也可以在if
语句和while
或until
循环中使用-在POSIX兼容的shell中。因此,尽管我有所保留,但它可能比我在2008年意识到的更广泛。对POSIX 2004和SUS/POSIX 1997的快速检查表明,这两个版本中都存在!
。请注意,
!
运算符必须出现在管道的 * 开头 *,并对整个管道的状态码取反(即 last 命令)。以下是一些例子。字符串
便携式答案-适用于古董 shell
在Bourne(Korn,POSIX,Bash)脚本中,我用途:
型
这是便携式的,因为它得到。“命令和参数”可以是流水线或其他复合命令序列。
not
命令'!'操作符,无论是内置在shell中还是由o/s提供,都不是通用的。这并不是很难写,虽然-下面的代码可以追溯到至少1991年(虽然我认为我写了一个更早的版本甚至更早)。不过,我不倾向于在脚本中使用它,因为它并不可靠。
型
当执行命令失败时,返回“success”,与“failure”相反。我们可以讨论“成功地什么都不做”的选择是否正确;也许它应该在没有被要求做任何事情的时候报告一个错误。'
"stderr.h"
'中的代码提供了简单的错误报告功能-我在任何地方都使用它。源代码的要求-看到我的个人资料页与我联系。cqoc49vn2#
在Bash中,使用!操作员在命令之前。例如:
字符串
mbzjlibv3#
您可以尝试:
字符串
或者只是:
型
inkz8wg94#
如果你没有使用Bash作为shell(例如:Git脚本或Puppet exec测试),您可以运行:
第一个月
-> retcode:0
echo '! ls /' | bash
个-> retcode:1
kmbjn2e35#
解决方案没有!,不带subshell,不带if,并且应该至少在Bash中工作:
字符串
oogrdqng6#
字符串
或者是
型
rur96b6h7#
注意:有时你会看到
!(command || other command)
。这里
! ls nonexistingpath && echo "yes, nonexistingpath doesn't exist."
就足够了。不需要子shell。
Git 2.22(2019年第二季度)通过以下方式说明了更好的形式:
Commit 74ec8cf,commit 3fae7ad,commit 0e67c32,commit 07353d9,commit 3bc2702,commit 8c3b9f7,commit 80a539a,commit c5c39f4(2019年3月13日)by SZEDER Gábor (
szeder
) .参见commit 99e37c2,commit 9f82b2a,commit 900721e(2019年3月13日)by Johannes Schindelin (
dscho
)。(由Junio C Hamano --
gitster
--合并至commit 579b75a,2019年4月25日)t9811-git-p4-label-import
:固定流水线否定在“
t9811-git-p4-label-import.sh
”中,测试“tag that cannot be exported
”运行:字符串
检查给定的字符串不是由'
p4 labels
'打印的。这是有问题的,因为根据POSIX:
“如果管道以保留字
!
开始,并且command1
是子shell命令,则应用程序应确保command1
开头的(
运算符与!
之间由一个或多个<blank>
字符分隔开。保留字
!
后面紧跟(
运算符的行为未指定。”虽然大多数常见的shell仍然将此'
!
'解释为“否定管道中最后一个命令的退出代码”,但'mksh/lksh
'不这样做,而是将其解释为负文件名模式。因此,它们试图运行由当前目录中的路径名组成的命令(它包含一个名为“
main
”的目录),当然,这会失败。我们可以简单地通过在'
!
'和'(
'之间添加一个空格来修复它,但是让我们通过删除不必要的子shell来修复它。特别是Commit 74ec8cf