Ini disebut operator shell dan ya, ada lebih banyak dari mereka. Saya akan memberikan gambaran singkat tentang yang paling umum di antara dua kelas utama, operator kontrol dan operator pengalihan , dan bagaimana mereka bekerja sehubungan dengan bash shell.
;
: Akan menjalankan satu perintah setelah yang lain selesai, terlepas dari hasil yang pertama.
command1 ; command2
Pertama command1
dijalankan, di latar depan, dan setelah selesai, command2
akan dijalankan.
Baris baru yang tidak dalam string literal atau setelah kata kunci tertentu tidak setara dengan operator titik koma. Daftar ;
perintah sederhana terbatas masih merupakan daftar - karena dalam parser shell masih harus terus membaca dalam perintah sederhana yang mengikuti ;
perintah sederhana terbatas sebelum dieksekusi, sedangkan baris baru dapat membatasi seluruh daftar perintah - atau daftar daftar. Perbedaannya halus, tetapi rumit: mengingat shell tidak memiliki keharusan sebelumnya untuk membaca data mengikuti baris baru, baris baru menandai titik di mana shell dapat mulai mengevaluasi perintah-perintah sederhana yang sudah dibaca, sedangkan ;
semi-colon tidak tidak.
&
: Ini akan menjalankan perintah di latar belakang, memungkinkan Anda untuk terus bekerja di shell yang sama.
command1 & command2
Di sini, command1
diluncurkan di latar belakang dan command2
mulai berjalan di latar depan segera, tanpa menunggu untuk command1
keluar.
Baris baru setelahnya command1
adalah opsional.
&&
: Digunakan untuk membangun DAN daftar, ini memungkinkan Anda untuk menjalankan satu perintah hanya jika yang lain berhasil keluar.
command1 && command2
Di sini, command2
akan dijalankan setelah command1
selesai dan hanya jika command1
berhasil (jika kode keluarnya adalah 0). Kedua perintah dijalankan di latar depan.
Perintah ini juga bisa ditulis
if command1
then command2
else false
fi
atau hanya if command1; then command2; fi
jika status pengembalian diabaikan.
||
: Digunakan untuk membuat daftar ATAU, ini memungkinkan Anda untuk menjalankan satu perintah hanya jika yang lain tidak berhasil.
command1 || command2
Di sini, command2
hanya akan berjalan jika command1
gagal (jika mengembalikan status keluar selain 0). Kedua perintah dijalankan di latar depan.
Perintah ini juga bisa ditulis
if command1
then true
else command2
fi
atau dengan cara yang lebih pendek if ! command1; then command2; fi
.
Perhatikan itu &&
dan ||
asosiatif kiri; lihat diutamakan operator logika shell &&, || untuk informasi lebih lanjut.
!
: Ini adalah kata yang dilindungi undang-undang yang bertindak sebagai operator "bukan" (tetapi harus memiliki pembatas), digunakan untuk meniadakan status pengembalian suatu perintah - mengembalikan 0 jika perintah mengembalikan status bukan nol, mengembalikan 1 jika mengembalikan status 0 Juga TIDAK logis untuk test
utilitas.
! command1
[ ! a = a ]
Dan operator BUKAN yang sebenarnya dalam Ekspresi Aritmatika:
$ echo $((!0)) $((!23))
1 0
Ini memungkinkan Anda untuk mengontrol input dan output dari perintah Anda. Mereka dapat muncul di mana saja dalam perintah sederhana atau dapat mengikuti perintah. Pengalihan diproses sesuai urutan kemunculannya, dari kiri ke kanan.
<
: Memberikan input ke perintah.
command < file.txt
Di atas akan mengeksekusi command
pada isi file.txt
.
<>
: sama seperti di atas, tetapi file terbuka dalam mode baca + tulis alih-alih hanya baca :
command <> file.txt
Jika file tidak ada, itu akan dibuat.
Operator itu jarang digunakan karena perintah umumnya hanya membaca dari stdin mereka, meskipun itu bisa berguna dalam sejumlah situasi tertentu .
>
: Mengarahkan output perintah ke file.
command > out.txt
Di atas akan menyimpan output command
sebagai out.txt
. Jika file ada, isinya akan ditimpa dan jika tidak ada maka akan dibuat.
Operator ini juga sering digunakan untuk memilih apakah sesuatu harus dicetak ke kesalahan standar atau output standar :
command >out.txt 2>error.txt
Pada contoh di atas, >
akan mengarahkan output standar dan 2>
mengarahkan ulang kesalahan standar. Output juga dapat diarahkan menggunakan 1>
tetapi, karena ini adalah default, 1
biasanya dihilangkan dan ditulis hanya sebagai >
.
Jadi, untuk menjalankan command
pada file.txt
dan menyimpan output dalam out.txt
dan pesan kesalahan di error.txt
Anda akan menjalankan:
command < file.txt > out.txt 2> error.txt
>|
: Apakah sama dengan >
, tetapi akan menimpa target, bahkan jika shell telah dikonfigurasi untuk menolak menimpa (dengan set -C
atau set -o noclobber
).
command >| out.txt
Jika out.txt
ada, output dari command
akan mengganti kontennya. Jika tidak ada maka akan dibuat.
>>
: Apakah sama dengan >
, kecuali bahwa jika file target ada, data baru ditambahkan.
command >> out.txt
Jika out.txt
ada, output dari command
akan ditambahkan padanya, setelah apa pun yang sudah ada di dalamnya. Jika tidak ada maka akan dibuat.
&>
, >&
, >>&
Dan &>>
: (non-standar). Arahkan masing-masing kesalahan standar dan output standar, menggantikan atau menambahkan.
command &> out.txt
Baik standard error dan output standar command
akan disimpan out.txt
, menimpa isinya atau membuatnya jika tidak ada.
command &>> out.txt
Seperti di atas, kecuali jika out.txt
ada, output dan kesalahan command
akan ditambahkan padanya.
The &>
varian berasal bash
, sedangkan >&
varian berasal dari csh (dekade sebelumnya). Keduanya bertentangan dengan operator shell POSIX lain dan tidak boleh digunakan dalam sh
skrip portabel .
<<
: Dokumen di sini. Ini sering digunakan untuk mencetak string multi-line.
command << WORD
Text
WORD
Di sini, command
akan mengambil semuanya hingga menemukan kemunculan berikutnya WORD
, Text
dalam contoh di atas, sebagai input. Meskipun WORD
sering EoF
atau variasi daripadanya, itu bisa berupa string alfanumerik (dan bukan hanya) yang Anda suka. Ketika WORD
dikutip, teks dalam dokumen di sini diperlakukan secara harfiah dan tidak ada ekspansi yang dilakukan (pada variabel misalnya). Jika tidak dikutip, variabel akan diperluas. Untuk detail lebih lanjut, lihat manual bash .
Jika Anda ingin menyalurkan output command << WORD ... WORD
langsung ke perintah atau perintah lain, Anda harus meletakkan pipa pada baris yang sama dengan << WORD
, Anda tidak dapat meletakkannya setelah KATA penghentian atau pada baris berikutnya. Sebagai contoh:
command << WORD | command2 | command3...
Text
WORD
<<<
: Berikut string, mirip dengan dokumen di sini, tetapi dimaksudkan untuk satu baris. Ini hanya ada di port Unix atau rc (dari mana asalnya), zsh, beberapa implementasi ksh, yash dan bash.
command <<< WORD
Apa pun yang diberikan saat WORD
diperluas dan nilainya diteruskan sebagai input command
. Ini sering digunakan untuk meneruskan konten variabel sebagai input ke perintah. Sebagai contoh:
$ foo="bar"
$ sed 's/a/A/' <<< "$foo"
bAr
# as a short-cut for the standard:
$ printf '%s\n' "$foo" | sed 's/a/A/'
bAr
# or
sed 's/a/A/' << EOF
$foo
EOF
Itu hanya mencakup operator paling umum dari kerang mirip Bourne. Beberapa shell memiliki beberapa operator pengalihan tambahan mereka sendiri.
bash
. Ini dipersiapkan sebagai tanya jawab kanonik untuk menutup berbagai pertanyaan "Apa yang dilakukan makhluk aneh ini" dan kebanyakan dari mereka adalah pengguna bash. Saya berharap orang lain akan melempar dan menjawab untuk cangkang non-bash, tetapi menyoroti bash-spesifik tertentu sangat masuk akal. Saya harus memeriksa, saya tidak tahu yang mana yang berada di atas kepala saya.&>
,,>>>
dan<<<
semuanya non-posix seperti referensi untuk karakter non-alphanum tidak-saja dalam nama-doc di sini. Jawaban ini juga membahas sangat sedikit tentang bagaimana mereka bekerja - misalnya, hampir lebih buruk daripada tidak berguna untuk berbicara tentang perintah sederhana dan perintah tanpa menjelaskan apa ini dan bagaimana shell memutuskan.false
) dan kode keluar 0 menunjukkan keberhasilan (tidaktrue
). Itu selalu menjadi jalan dan cukup standar. Kode keluar non-0 menunjukkan kesalahan di setiap lingkungan yang saya tahu.Peringatan tentang '>'
Pemula Unix yang baru belajar tentang pengalihan I / O (
<
dan>
) sering mencoba hal-hal sepertiatau
atau, hampir setara,
(
grep
,sed
,cut
,sort
, Danspell
adalah contoh perintah yang orang tergoda untuk digunakan dalam konstruksi seperti ini.) Pengguna terkejut menemukan bahwa skenario ini menghasilkan file menjadi kosong.Sebuah nuansa yang tampaknya tidak disebutkan dalam jawaban lainnya dapat ditemukan bersembunyi dalam kalimat pertama dari Pengalihan bagian dari bash (1) :
Lima kata pertama harus tebal, miring, bergaris bawah, diperbesar, berkedip, berwarna merah, dan ditandai dengan ikon, untuk menekankan fakta bahwa shell melakukan pengalihan yang diminta sebelum perintah dijalankan . Dan ingat juga
Jadi, dalam contoh ini:
shell membuka
roster
file untuk ditulis, memotongnya (yaitu, membuang semua isinya), sebelumsort
program mulai berjalan. Secara alami, tidak ada yang bisa dilakukan untuk memulihkan data.Orang mungkin naif mengharapkan itu
mungkin lebih baik. Karena shell menangani pengalihan dari kiri ke kanan, shell terbuka
poem
untuk membaca (untuktr
input standar) sebelum membukanya untuk menulis (untuk output standar). Tapi itu tidak membantu. Meskipun urutan operasi ini menghasilkan dua pegangan file, mereka berdua menunjuk ke file yang sama. Ketika shell membuka file untuk dibaca, isinya masih ada, tetapi mereka masih musnah sebelum program dieksekusi.Jadi, apa yang harus dilakukan?
Solusi meliputi:
Periksa apakah program yang Anda jalankan memiliki kapabilitas sendiri, internal, untuk menentukan ke mana output berjalan. Ini sering ditunjukkan dengan token
-o
(atau--output=
). Khususnya,kira-kira setara dengan
kecuali, dalam kasus pertama,
sort
program membuka file output. Dan cukup pintar untuk tidak membuka file output sampai setelah membaca semua file input.Demikian pula, setidaknya beberapa versi
sed
memiliki-i
(edit i n tempat) pilihan yang dapat digunakan untuk menulis output kembali ke file input (sekali lagi, setelah semua masukan sudah dibaca). Editor sepertied
/ex
,emacs
,pico
, danvi
/vim
memungkinkan pengguna untuk mengedit file teks dan menyimpan teks diedit di file asli. Perhatikan bahwaed
(setidaknya) dapat digunakan secara non-interaktif.vi
memiliki fitur terkait. Jika Anda mengetik , itu akan menulis isi buffer edit , membaca hasilnya, dan memasukkannya ke buffer (mengganti konten asli).:%!command
Entercommand
Sederhana tetapi efektif:
Ini memiliki kelemahan bahwa, jika
input_file
merupakan tautan, tautan itu (mungkin) akan digantikan oleh file terpisah. Juga, file baru akan dimiliki oleh Anda, dengan perlindungan default. Secara khusus, ini membawa risiko bahwa file tersebut pada akhirnya akan dapat dibaca dunia, bahkan jika aslinyainput_file
tidak.Variasi:
command … input_file > temp_file && cp temp_file input_file && rm temp_file
yang masih akan (berpotensi) meninggalkan
temp_file
dunia terbaca. Bahkan lebih baik:cp input_file temp_file && command … temp_file > input_file && rm temp_file
Ini mempertahankan status tautan, pemilik, dan mode (perlindungan) file, berpotensi dengan biaya dua kali lipat I / O. (Anda mungkin perlu menggunakan opsi suka
-a
atau-p
aktifcp
untuk mengatakannya untuk mempertahankan atribut.)command … input_file > temp_file &&
cp --attributes-only --preserve=all input_file temp_file &&
mv temp_file input_file
(dipecah menjadi baris terpisah hanya untuk keterbacaan) Ini mempertahankan mode file (dan, jika Anda root, pemilik), tetapi membuatnya dimiliki oleh Anda (jika Anda bukan root), dan menjadikannya baru, file terpisah.
Blog ini ("Di-tempat" mengedit file) menyarankan dan menjelaskan
Ini mensyaratkan bahwa
command
mampu memproses input standar (tetapi hampir semua filter dapat). Blog itu sendiri menyebut ini kludge berisiko dan mencegah penggunaannya. Dan ini juga akan membuat file baru yang terpisah (tidak terkait dengan apa pun), yang dimiliki oleh Anda dan dengan izin default.Paket moreutils memiliki perintah yang disebut
sponge
:Lihat jawaban ini untuk informasi lebih lanjut.
Inilah sesuatu yang mengejutkan saya: sintaksis mengatakan :
Berikut ini mungkin berfungsi dalam kasus itu:
sort
atautr
tanpa satu-d
atau-s
opsi), Anda dapat mencoba Lihat jawaban ini dan jawaban ini untuk informasi lebih lanjut, termasuk penjelasan di atas, dan alternatif yang berfungsi jika perintah Anda dijamin untuk menghasilkan jumlah data output yang sama dengan input atau kurang (misalnyagrep
,, ataucut
). Jawaban-jawaban ini memiliki keuntungan bahwa mereka tidak memerlukan ruang kosong (atau mereka membutuhkan sangat sedikit). Jawaban di atas dari formulir jelas mensyaratkan bahwa ada cukup ruang kosong bagi sistem untuk dapat menyimpan seluruh file input (lama) dan file output (baru) secara bersamaan; ini tidak jelas benar untuk sebagian besar solusi lain (misalnya, dan ) juga. Pengecualian: mungkin akan membutuhkan banyak ruang kosong, karenacommand … input_file > temp_file && …
sed -i
sponge
sort … | dd …
sort
perlu membaca semua inputnya sebelum dapat menulis output apa pun, dan mungkin buffer paling jika tidak semua data dalam file sementara.dd
jawaban di atas. The sintaks membuka file bernama pada file descriptor untuk kedua input dan output , tanpa truncating itu - semacam kombinasi dan . Catatan: Beberapa program (misalnya, dan ) mungkin menolak untuk berjalan dalam skenario ini karena mereka dapat mendeteksi bahwa input dan output adalah file yang sama. Lihat jawaban ini untuk pembahasan di atas, dan skrip yang membuat jawaban ini berfungsi jika perintah Anda dijamin untuk menghasilkan jumlah data output yang sama dengan input atau kurang . Peringatan: Saya belum menguji skrip Peter, jadi saya tidak menjaminnya.n<> file
n
n<
n>
cat
grep
Jadi, apa pertanyaannya?
Ini telah menjadi topik populer tentang U&L; itu dibahas dalam pertanyaan-pertanyaan berikut:
iconv
mengganti file input dengan output yang dikonversi?shuf file > file
meninggalkan file kosong?sort
perintah ini memberi saya file kosong?tr
stdout ke file... dan itu tidak termasuk Super User atau Ask Ubuntu. Saya telah memasukkan banyak informasi dari jawaban atas pertanyaan di atas dalam jawaban ini, tetapi tidak semua. (Yaitu, untuk informasi lebih lanjut, baca pertanyaan-pertanyaan yang tercantum di atas dan jawabannya.)
PS Saya tidak memiliki afiliasi dengan blog yang saya kutip di atas.
sumber
/tmp
.dash
akan menjadi shell recovery default pada Ubuntu dan tidak hanya tidak mengerti<<<
herestring, tetapi juga mendapat pipa anonim untuk<<
heredocuments dan tidak main-main dengan${TMPDIR:-/tmp}
untuk itu tujuan sama sekali. Lihat ini atau ini untuk demo tentang penanganan dokumen di sini. Juga mengapa jumlah output yang sama atau kurang peringatan?dd … conv=notrunc
dan1<>
jawaban tidak pernah memotong file output, jadi, jika output dari perintah kurang dari input (misalnya,grep
), akan ada beberapa byte asli yang tersisa di akhir file. Dan, jika output lebih besar dari input (misalnya,cat -n
,nl
, atau (berpotensi)grep -n
), ada risiko Timpa data lama sebelum Anda membacanya.Pengamatan lebih pada
;
,&
,(
dan)
Perhatikan bahwa beberapa perintah dalam jawaban terdon mungkin nol. Misalnya, bisa dibilang
(tanpa
command2
). Ini setara dengan(Yaitu, itu hanya berjalan
command1
di latar depan dan menunggu sampai selesai. Sebanding,(tanpa
command2
) akan diluncurkancommand1
di latar belakang dan kemudian segera mengeluarkan prompt shell lainnya.Sebaliknya,
command1 &&
,command1 ||
, dancommand1 |
tidak masuk akal. Jika Anda mengetik salah satu dari ini, shell akan (mungkin) mengasumsikan bahwa perintah dilanjutkan ke baris lain. Ini akan menampilkan prompt shell sekunder (lanjutan), yang biasanya diatur ke>
, dan terus membaca. Dalam skrip shell, itu hanya akan membaca baris berikutnya dan menambahkannya ke apa yang sudah dibaca. (Hati-hati: ini mungkin bukan yang Anda inginkan terjadi.)Catatan: beberapa versi beberapa shell mungkin memperlakukan perintah yang tidak lengkap sebagai kesalahan. Dalam kasus seperti itu (atau, pada kenyataannya, dalam kasus apa pun di mana Anda memiliki perintah yang panjang), Anda dapat meletakkan garis miring terbalik (
\
) di akhir baris untuk memberi tahu shell untuk melanjutkan membaca perintah di baris lain:atau
Seperti kata terdon,
(
dan)
dapat digunakan untuk mengelompokkan perintah. Pernyataan bahwa mereka “tidak benar-benar relevan” dengan diskusi itu masih bisa diperdebatkan. Beberapa perintah dalam jawaban terdon mungkin adalah grup perintah . Sebagai contoh,Melakukan hal ini:
command1
dan tunggu sampai selesai.command2
dan tunggu sampai selesai.Lalu, jika
command2
berhasil,command3
dan tunggu sampai selesai.command4
dan tunggu sampai selesai.Jika
command2
gagal, hentikan pemrosesan baris perintah.Di luar kurung,
|
mengikat dengan sangat erat, jadisetara dengan
dan
&&
dan||
ikat lebih ketat daripada;
, jadisetara dengan
yaitu,
command3
akan dieksekusi terlepas dari status keluar daricommand1
dan / ataucommand2
.sumber
;
dengan sendirinya (atau tanpa perintah sebelumnya) adalah kesalahan sintaks, dan bukan pernyataan kosong. Jadi; ;
ini adalah kesalahan. (Perangkap umum untuk pengguna baru, IMHO). Juga:;;
adalah pembatas khusus, untukcase
pernyataan.;
,&&
,||
,&
, dan|
, kesalahan jika mereka muncul dengan apa-apa sebelumnya mereka. Juga, terdon menjawab;;
(secara singkat) dalam jawabannya.linebreak
token dalam tata bahasa shell POSIX. Jadi mungkin aman untuk mengatakan bahwa semua shell yang mendukung POSIX akan menerimanya. Saya mendukung pernyataan saya sebagai penafian umum; jika Anda menemukan shell pra-POSIX yang cukup lama, seperti shell Bourne yang sebenarnya atau yang lebih tua, semua taruhan dimatikan.