Saya ingin menggabungkan beberapa kondisi dalam pernyataan if shell, dan meniadakan kombinasi. Saya memiliki kode kerja berikut untuk kombinasi kondisi sederhana:
if [ -f file1 ] && [ -f file2 ] && [ -f file3 ] ; then
# do stuff with the files
fi
Ini berfungsi dengan baik. Jika saya ingin meniadakannya, saya dapat menggunakan kode kerja berikut:
if ! ( [ -f file1 ] && [ -f file2 ] && [ -f file3 ] ) ; then
echo "Error: You done goofed."
exit 1
fi
# do stuff with the files
Ini juga berfungsi seperti yang diharapkan. Namun, terpikir olehku bahwa aku tidak tahu apa yang sebenarnya dilakukan kurung di sana. Saya ingin menggunakannya hanya untuk pengelompokan, tetapi apakah ini benar-benar menghasilkan subkulit? (Bagaimana saya bisa tahu?) Jika demikian, apakah ada cara untuk mengelompokkan kondisi tanpa menelurkan subkulit?
bash
shell-script
Wildcard
sumber
sumber
if ! [ -f file1 ] || ! [ -f file 2 ] || ! [ -f file3 ] ; then
tapi saya ingin jawaban yang lebih umum.if [[ ! -f file1 ]] && [[ ! -f file2 ]]; then
if [ ! 1 -eq 2 ] && [ ! 2 -eq 3 ]; then echo yep; fi
dan berhasil. Saya selalu menulis tes dengan kawat gigi ganda sebagai kebiasaan. Juga, untuk memastikannya tidakbash
, saya diuji lebih lanjutif /bin/test ! 1 -eq 2 && /bin/test ! 2 -eq 3 ; then echo yep; fi
dan berfungsi seperti itu juga.[ ! -e file/. ] && [ -r file ]
akan menjatuhkan direktori. Meniadakannya sesuka Anda. tentu saja, itulah yang-d
dilakukannya.Jawaban:
Anda harus menggunakan
{ list;}
alih-alih(list)
:Keduanya adalah Perintah Pengelompokan , tetapi
{ list;}
mengeksekusi perintah di lingkungan shell saat ini.Perhatikan bahwa,
;
dalam{ list;}
diperlukan untuk membatasi daftar dari}
kata terbalik, Anda dapat menggunakan pembatas lainnya juga. Ruang (atau pembatas lainnya) setelahnya{
juga diperlukan.sumber
awk
lebih sering menggunakan kurung kurawal daripada dibash
) adalah kebutuhan untuk spasi putih setelah kurawal kurawal terbuka. Anda menyebutkan "Anda dapat menggunakan pembatas lain juga"; ada contoh?zsh
, Anda dapat menggunakan spasi putih&
ini juga merupakan pemisah, Anda dapat menggunakan{ echo 1;:&}
, beberapa baris juga dapat digunakan.they must be separated from list by whitespace or another shell metacharacter.
Dalam pesta mereka:metacharacter: | & ; ( ) < > space tab
. Untuk tugas khusus ini, saya yakin semua& ; ) space tab
akan bekerja. .... .... Dari zsh (sebagai komentar)each sublist is terminated by
&',
&!', or a newline.
Anda dapat menggunakan
test
fungsionalitas sepenuhnya untuk mencapai apa yang Anda inginkan. Dari halaman manual daritest
:Jadi kondisi Anda dapat terlihat seperti:
Untuk meniadakan penggunaan tanda kurung lolos:
sumber
Untuk portable meniadakan bersyarat kompleks dalam shell, Anda harus baik menerapkan hukum De Morgan dan mendorong negasi semua jalan ke bawah dalam
[
panggilan ...... atau Anda harus menggunakan
then :; else
...if ! command
tidak tersedia dan tidak mudah dibawa[[
.Jika Anda tidak membutuhkan portabilitas total, jangan tulis skrip shell . Anda sebenarnya lebih mungkin menemukan
/usr/bin/perl
Unix yang dipilih secara acak daripada Andabash
.sumber
!
adalah POSIX yang saat ini cukup portabel. Bahkan sistem yang masih menggunakan shell Bourne juga memiliki POSIX sh di tempat lain pada sistem file yang dapat Anda gunakan untuk menginterpretasikan sintaks standar Anda./bin/sh
. Skrip autoconf melakukan seperti yang Anda sarankan, tapi saya pikir kita semua tahu betapa sedikitnya dukungan yang ada.yang lain telah mencatat pengelompokan
{
perintah majemuk;}
, tetapi jika Anda melakukan tes yang identik pada set Anda mungkin ingin menggunakan jenis yang berbeda:... seperti yang ditunjukkan di tempat lain
{ :;}
, tidak ada kesulitan yang terlibat dengan perintah gabungan bersarang ...Perhatikan bahwa tes di atas (biasanya) untuk file biasa . Jika Anda hanya mencari file yang ada dan dapat dibaca yang bukan merupakan direktori:
Jika Anda tidak peduli apakah itu direktori atau tidak:
... berfungsi untuk semua file yang dapat dibaca dan diakses , tetapi kemungkinan akan hang untuk fifos tanpa penulis.
sumber
Ini bukan jawaban penuh untuk pertanyaan utama Anda, tetapi saya perhatikan bahwa Anda menyebutkan pengujian gabungan (file yang dapat dibaca) dalam komentar; misalnya,
Anda dapat menggabungkan ini sedikit dengan mendefinisikan fungsi shell; misalnya,
Tambahkan penanganan kesalahan ke (misalnya,
[ $# = 1 ]
) secukupnya.if
Pernyataan pertama , di atas, sekarang dapat diringkas menjadidan Anda dapat mempersingkat ini lebih jauh dengan mempersingkat nama fungsi. Demikian juga, Anda bisa mendefinisikan
not_readable_file()
(ataunrf
singkatnya) dan memasukkan negasi dalam fungsi.sumber
readable_files() { [ $# -eq 0 ] && return 1 ; for file in "$@" ; do [ -f "$file" ] && [ -r "$file" ] || return 1 ; done ; }
(Penafian: Saya menguji kode ini dan berfungsi tetapi itu bukan satu-liner. Saya menambahkan tanda titik koma untuk posting di sini tetapi tidak menguji penempatan mereka.)if readable_files file1 file2 file3
tidak akan tahu apakah fungsi itu melakukan DAN atau ATAU - meskipun (a) saya kira itu cukup intuitif, (b) jika Anda tidak mendistribusikan skrip, itu cukup baik jika Anda memahaminya, dan (c) karena saya menyarankan menyingkat nama fungsi menjadi ketidakjelasan, saya tidak dapat berbicara tentang keterbacaan. … (Lanjutan)for file in "$@" ; do
denganfor file do
- defaultnya adalahin "$@"
, dan (agak kontra-intuitif);
tidak hanya tidak perlu tetapi sebenarnya tidak disarankan.Anda dapat meniadakan di dalam tes brace juga, jadi untuk menggunakan kembali kode asli Anda:
sumber
||
bukannya&&
||
akan mengeksekusi predikat jika ada file tidak ada, tidak jika dan hanya jika semua file tidak ada. BUKAN (A DAN B DAN C) sama dengan (BUKAN A) DAN (BUKAN B) DAN (BUKAN C); lihat pertanyaan aslinya.||
bukan&&
. Lihat komentar pertama saya di bawah pertanyaan saya sendiri.not (a and b)
sama dengan(not a) or (not b)
. Lihat en.wikipedia.org/wiki/De_Morgan%27s_lawsYa, perintah di dalam
(...)
dijalankan dalam subkulit.Untuk menguji apakah Anda berada dalam subkulit Anda dapat membandingkan PID dari shell Anda saat ini dengan PID dari shell interaktif.
Contoh output, menunjukkan bahwa kurung menelurkan subkulit dan kurung kurawal tidak:
sumber
()
tidak menelurkan subkulit..mungkin{}
echo $$ && ( echo $$ )
membandingkan PID dan semuanya sama, tetapi tepat sebelum saya mengirimkan komentar yang mengatakan Anda salah, saya mencoba satu hal lagi.echo $BASHPID && ( echo $BASHPID )
memberikan PID yang berbedaecho $BASHPID && { echo $BASHPID; }
memberikan PID yang sama seperti yang Anda sarankan akan terjadi. Terima kasih atas pendidikannya$BASHPID
, itu hal lain yang saya lewatkan.