Saya mencari sederhana, tapi cross-platform meniadakan -process yang meniadakan nilai proses pengembalian. Ini harus memetakan 0 ke beberapa nilai! = 0 dan nilai apa pun! = 0 ke 0, yaitu perintah berikut harus mengembalikan "ya, tidak ada jalur yang ada":
ls nonexistingpath | negate && echo "yes, nonexistingpath doesn't exist."
The! - Operatornya bagus tapi sayangnya tidak bergantung pada shell.
shell
cross-platform
negate
secr
sumber
sumber
Jawaban:
Sebelumnya, jawabannya disajikan dengan apa yang sekarang menjadi bagian pertama sebagai bagian terakhir.
POSIX Shell menyertakan
!
operatorMengaduk-aduk spesifikasi shell untuk masalah lain, saya baru-baru ini (September 2015) memperhatikan bahwa shell POSIX mendukung
!
operator. Misalnya, ini terdaftar sebagai kata yang dipesan dan dapat muncul di awal pipeline - di mana perintah sederhana adalah kasus khusus 'pipeline'. Oleh karena itu, dapat digunakan dalamif
pernyataan danwhile
atauuntil
loop juga - dalam shell yang sesuai dengan POSIX. Akibatnya, meskipun saya ragu, ini mungkin lebih banyak tersedia daripada yang saya sadari pada tahun 2008. Pemeriksaan cepat dari POSIX 2004 dan SUS / POSIX 1997 menunjukkan bahwa!
ada di kedua versi tersebut.Perhatikan bahwa
!
operator harus muncul di awal pipeline dan meniadakan kode status dari seluruh pipeline (yaitu perintah terakhir ). Berikut ini beberapa contohnya.# Simple commands, pipes, and redirects work fine. $ ! some-command succeed; echo $? 1 $ ! some-command fail | some-other-command fail; echo $? 0 $ ! some-command < succeed.txt; echo $? 1 # Environment variables also work, but must come after the !. $ ! RESULT=fail some-command; echo $? 0 # A more complex example. $ if ! some-command < input.txt | grep Success > /dev/null; then echo 'Failure!'; recover-command; mv input.txt input-failed.txt; fi Failure! $ ls *.txt input-failed.txt
Jawaban portabel - bekerja dengan cangkang antik
Dalam skrip Bourne (Korn, POSIX, Bash), saya menggunakan:
if ...command and arguments... then : it succeeded else : it failed fi
Ini portabel. 'Perintah dan argumen' dapat berupa pipa atau rangkaian perintah gabungan lainnya.
Sebuah
not
perintah'!' operator, apakah built-in ke shell Anda atau disediakan oleh o / s, tidak tersedia secara universal. Tidak terlalu sulit untuk menulis, meskipun - kode di bawah ini berasal dari setidaknya tahun 1991 (meskipun saya pikir saya menulis versi sebelumnya lebih lama lagi). Saya tidak cenderung menggunakan ini dalam skrip saya, karena tidak tersedia secara andal.
/* @(#)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); }
Ini mengembalikan 'sukses', kebalikan dari kegagalan, ketika gagal menjalankan perintah. Kita dapat memperdebatkan apakah opsi 'tidak berhasil' itu benar; mungkin itu harus melaporkan kesalahan ketika tidak diminta untuk melakukan apapun. Kode dalam '
"stderr.h"
' menyediakan fasilitas pelaporan kesalahan sederhana - saya menggunakannya di mana-mana. Kode sumber atas permintaan - lihat halaman profil saya untuk menghubungi saya.sumber
!
operator. Ini berhasil bagi saya:! MY_ENV=value my_command
ldd foo.exe | ! grep badlib
tetapi Anda dapat melakukannya! ldd foo.exe | grep badlib
jika Anda ingin status keluar menjadi 0 jika badlib tidak ditemukan di foo.exe. Secara semantik Anda ingin membalikgrep
status, tetapi membalik seluruh pipa akan memberikan hasil yang sama.ldd foo.exe | { ! grep badlib; }
(meskipun mengganggu, terutama titik koma; Anda dapat menggunakan sub-shell lengkap dengan(
dan)
dan tanpa titik koma). OTOH, objeknya adalah untuk membalik status keluar dari pipa, dan itu adalah status keluar dari perintah terakhir (kecuali di Bash, kadang-kadang).!
perintah memiliki interaksi yang tidak diinginkanset -e
, yaitu menyebabkan perintah berhasil dengan kode keluar 0 atau bukan nol, alih-alih hanya berhasil dengan kode keluar bukan nol. Apakah ada cara ringkas untuk membuatnya berhasil hanya dengan kode keluar bukan nol?Di Bash, gunakan! operator sebelum perintah. Misalnya:
! ls nonexistingpath && echo "yes, nonexistingpath doesn't exist"
sumber
Kamu bisa mencoba:
ls nonexistingpath || echo "yes, nonexistingpath doesn't exist."
atau hanya:
sumber
!
tidak dapat digunakan dengangit bisect run
, atau setidaknya saya tidak tahu caranya.!
kasus tersebut.Jika entah bagaimana terjadi bahwa Anda tidak memiliki Bash sebagai shell Anda (misalnya: skrip git, atau tes eksekutif boneka), Anda dapat menjalankan:
echo '! ls notexisting' | bash
-> kode ulang: 0
echo '! ls /' | bash
-> kode ulang: 1
sumber
! ls nonexistingpath && echo "yes, nonexistingpath doesn't exist."
atau
ls nonexistingpath || echo "yes, nonexistingpath doesn't exist."
sumber
$?
akan berbeda. Yang pertama mungkin pergi$?=1
jikanonexistingpath
memang benar ada. Yang kedua selalu pergi$?=0
. Jika Anda menggunakan ini dalam Makefile dan perlu mengandalkan nilai kembalian, Anda harus berhati-hati.Catatan: terkadang Anda akan melihat
!(command || other command)
.Ini
! ls nonexistingpath && echo "yes, nonexistingpath doesn't exist."
sudah cukup.Tidak perlu sub-shell.
Git 2.22 (Q2 2019) menggambarkan bentuk yang lebih baik dengan:
Komit 74ec8cf , komit 3fae7ad , komit 0e67c32 , komit 07353d9 , komit 3bc2702 , komit 8c3b9f7 , komit 80a539a , komit c5c39f4 (13 Mar 2019) oleh SZEDER Gábor (
szeder
) .Lihat commit 99e37c2 , commit 9f82b2a , commit 900721e (13 Mar 2019) oleh Johannes Schindelin (
dscho
) .(Digabung oleh Junio C Hamano -
gitster
- di commit 579b75a , 25 Apr 2019)sumber
Solusi tanpa!, Tanpa subkulit, tanpa if, dan harus berfungsi setidaknya di bash:
ls nonexistingpath; test $? -eq 2 && echo "yes, nonexistingpath doesn't exist." # alternatively without error message and handling of any error code > 0 ls nonexistingpath 2>/dev/null; test $? -gt 0 && echo "yes, nonexistingpath doesn't exist."
sumber