Menekan jejak eksekusi untuk perintah gema?

29

Saya menjalankan skrip shell dari Jenkins, yang memulai skrip shell dengan opsi shebang #!/bin/sh -ex.

Menurut Bash Shebang untuk boneka? ,, -x"menyebabkan shell mencetak jejak eksekusi", yang bagus untuk sebagian besar tujuan - kecuali untuk gema:

echo "Message"

menghasilkan output

+ echo "Message"
Message

yang agak berlebihan, dan terlihat agak aneh. Apakah ada cara untuk membiarkan -xdiaktifkan, tetapi hanya output

Message

alih-alih dua baris di atas, mis. dengan mengawali perintah echo dengan karakter perintah khusus, atau mengarahkan ulang output?

Kristen
sumber

Jawaban:

20

Ketika Anda sampai di leher Anda dalam buaya, mudah untuk melupakan bahwa tujuannya adalah untuk mengeringkan rawa.                   - Pepatah populer

Pertanyaannya adalah tentang echo, namun sebagian besar jawaban sejauh ini berfokus pada bagaimana menyelinap set +xperintah. Ada solusi yang lebih sederhana, lebih langsung:

{ echo "Message"; } 2> /dev/null

(Saya mengakui bahwa saya mungkin tidak memikirkan { …; } 2> /dev/null jika saya tidak melihatnya dalam jawaban sebelumnya.)

Ini agak rumit, tetapi, jika Anda memiliki blok echoperintah berturut-turut , Anda tidak perlu melakukannya pada masing-masing secara individual:

{
  echo "The quick brown fox"
  echo "jumps over the lazy dog."
} 2> /dev/null

Perhatikan bahwa Anda tidak perlu titik koma saat memiliki baris baru.

Anda dapat mengurangi beban pengetikan dengan menggunakan ide kenorb untuk membuka /dev/nullsecara permanen pada deskriptor file non-standar (misalnya, 3) dan kemudian mengatakan 2>&3alih-alih 2> /dev/nullsepanjang waktu.


Empat jawaban pertama pada saat penulisan ini memerlukan melakukan sesuatu yang istimewa (dan, dalam kebanyakan kasus, rumit) setiap kali Anda melakukan suatu echo. Jika Anda benar-benar ingin semua echo perintah untuk menekan jejak eksekusi (dan mengapa Anda tidak melakukannya?), Anda dapat melakukannya secara global, tanpa mengeluarkan banyak kode. Pertama, saya perhatikan bahwa alias tidak dilacak:

$ myfunc()
> {
>     date
> }
$ alias myalias="date"
$ set -x
$ date
+ date
Mon, Oct 31, 2016  0:00:00 AM           # Happy Halloween!
$ myfunc
+ myfunc                                # Note that function call is traced.
+ date
Mon, Oct 31, 2016  0:00:01 AM
$ myalias
+ date                                  # Note that it doesn’t say  + myalias
Mon, Oct 31, 2016  0:00:02 AM

(Perhatikan bahwa cuplikan skrip berikut berfungsi jika shebang #!/bin/sh, bahkan jika /bin/shtautan ke bash. Tetapi, jika shebang adalah #!/bin/bash, Anda perlu menambahkan shopt -s expand_aliasesperintah untuk membuat alias agar bekerja dalam skrip.)

Jadi, untuk trik pertama saya:

alias echo='{ set +x; } 2> /dev/null; builtin echo'

Sekarang, ketika kita mengatakan echo "Message", kita memanggil alias, yang tidak bisa dilacak. Alias ​​mematikan opsi jejak, sementara menekan pesan jejak dari setperintah (menggunakan teknik yang disajikan pertama dalam jawaban user5071535 ), dan kemudian menjalankan echoperintah yang sebenarnya . Ini memungkinkan kita mendapatkan efek yang mirip dengan jawaban user5071535 tanpa perlu mengedit kode di setiap echo perintah. Namun, mode jejak daun ini dimatikan. Kami tidak dapat memasukkan set -xalias ke (atau setidaknya tidak mudah) karena alias hanya memungkinkan string untuk diganti dengan kata; tidak ada bagian dari string alias yang dapat disuntikkan ke perintah setelah argumen (misalnya, "Message"). Jadi, misalnya, jika skripnya berisi

date
echo "The quick brown fox"
echo "jumps over the lazy dog."
date

hasilnya akan

+ date
Mon, Oct 31, 2016  0:00:03 AM
The quick brown fox
jumps over the lazy dog.
Mon, Oct 31, 2016  0:00:04 AM           # Note that it doesn’t say  + date

jadi Anda masih perlu mengaktifkan kembali opsi jejak setelah menampilkan pesan - tetapi hanya sekali setelah setiap blokecho perintah berturut-turut :

date
echo "The quick brown fox"
echo "jumps over the lazy dog."
set -x
date


Akan lebih baik jika kita bisa membuat set -xotomatis setelah echo- dan kita bisa, dengan sedikit tipu daya. Tetapi sebelum saya sajikan itu, pertimbangkan ini. OP dimulai dengan skrip yang menggunakan #!/bin/sh -exshebang. Secara implisit pengguna dapat menghapus xdari shebang dan memiliki skrip yang bekerja secara normal, tanpa penelusuran jejak. Alangkah baiknya jika kita bisa mengembangkan solusi yang mempertahankan properti itu. Beberapa jawaban pertama di sini gagal properti itu karena mereka melacak "kembali" pada setelah echopernyataan, tanpa syarat, tanpa memperhatikan apakah itu sudah aktif.  Jawaban ini jelas gagal mengenali masalah itu, karena ia menggantikan echooutput dengan jejak output; oleh karena itu, semua pesan hilang jika penelusuran dimatikan. Saya sekarang akan menyajikan solusi yang ternyata melacak kembali setelah echopernyataan bersyarat - hanya jika sudah aktif. Menurunkan versi ini menjadi solusi yang mengubah penelusuran "kembali" tanpa syarat adalah sepele dan dibiarkan sebagai latihan.

alias echo='{ save_flags="$-"; set +x;} 2> /dev/null; echo_and_restore'
echo_and_restore() {
        builtin echo "$*"
        case "$save_flags" in
         (*x*)  set -x
        esac
}

$-adalah daftar opsi; gabungan huruf yang sesuai dengan semua opsi yang ditetapkan. Misalnya, jika edan xopsi diatur, maka $-akan ada serakan huruf yang mencakup edan x. Alias ​​baru saya (di atas) menyimpan nilai $-sebelum mematikan penelusuran. Kemudian, dengan pelacakan dimatikan, itu melemparkan kontrol ke fungsi shell. Fungsi itu melakukan yang sebenarnya echo dan kemudian memeriksa untuk melihat apakah xopsi dihidupkan ketika alias dipanggil. Jika opsi diaktifkan, fungsi akan mengaktifkannya kembali; jika tidak aktif, fungsi akan mati.

Anda dapat memasukkan tujuh baris di atas (delapan, jika Anda menyertakan a shopt) di awal skrip dan biarkan sisanya sendiri.

Ini akan memungkinkan Anda

  1. untuk menggunakan salah satu dari garis shebang berikut:
    #! / bin / sh -ex
    #! / bin / sh -e
    #! / bin / sh –x
    atau sekadar polos
    #! / bin / sh
    dan itu harus bekerja seperti yang diharapkan.
  2. untuk memiliki kode seperti
    (shebang) 
    perintah 1
     perintah 2
     perintah 3
    set -x
    perintah 4
     perintah 5
     perintah 6
    set + x
    perintah 7
     perintah 8
     perintah 9
    dan
    • Perintah 4, 5, dan 6 akan dilacak - kecuali salah satunya adalah echo, dalam hal ini akan dieksekusi tetapi tidak dilacak. (Tetapi meskipun perintah 5 adalah echo, perintah 6 masih akan dilacak.)
    • Perintah 7, 8, dan 9 tidak akan dilacak. Bahkan jika perintah 8 adalah echo, perintah 9 masih tidak akan dilacak.
    • Perintah 1, 2, dan 3 akan dilacak (seperti 4, 5, dan 6) atau tidak (seperti 7, 8, dan 9) tergantung pada apakah shebang termasuk x.

PS Saya telah menemukan bahwa, di sistem saya, saya dapat meninggalkan builtinkata kunci di jawaban tengah saya (yang hanya alias untuk echo). Ini tidak mengejutkan; bash (1) mengatakan bahwa, selama ekspansi alias, ...

... kata yang identik dengan alias yang diperluas tidak diperluas untuk kedua kalinya. Ini berarti bahwa seseorang dapat alias lsuntuk ls -F, misalnya, dan bash tidak mencoba memperluas teks pengganti secara rekursif.

Tidak terlalu mengejutkan, jawaban terakhir (yang dengan echo_and_restore) gagal jika builtinkata kunci dihilangkan 1 . Tapi, anehnya itu berfungsi jika saya menghapus builtindan mengganti urutan:

echo_and_restore() {
        echo "$*"
        case "$save_flags" in
         (*x*)  set -x
        esac
}
alias echo='{ save_flags="$-"; set +x;} 2> /dev/null; echo_and_restore'

__________
1  Tampaknya menimbulkan perilaku yang tidak terdefinisi. Saya telah melihat

  • loop tak terbatas (mungkin karena rekursi tak terbatas),
  • sebuah /dev/null: Bad addresspesan kesalahan, dan
  • dump inti.
G-Man Mengatakan 'Reinstate Monica'
sumber
2
Saya telah melihat beberapa trik sulap luar biasa yang dilakukan dengan alias, jadi saya tahu pengetahuan saya tidak lengkap. Jika ada yang bisa menyajikan cara untuk melakukan yang setara echo +x; echo "$*"; echo -xdalam alias, saya ingin melihatnya.
G-Man Mengatakan 'Reinstate Monica'
11

Saya menemukan solusi parsial di InformIT :

#!/bin/bash -ex
set +x; 
echo "shell tracing is disabled here"; set -x;
echo "but is enabled here"

output

set +x; 
shell tracing is disabled here 
+ echo "but is enabled here"
but is enabled here

Sayangnya, itu masih menggema set +x, tapi setidaknya itu sepi setelah itu. jadi setidaknya solusi parsial untuk masalah ini.

Tetapi apakah mungkin ada cara yang lebih baik untuk melakukan ini? :)

Kristen
sumber
2

Cara ini meningkatkan solusi Anda sendiri dengan menyingkirkan set +xoutput:

#!/bin/bash -ex
{ set +x; } 2>/dev/null
echo "shell tracing is disabled here"; set -x;
echo "but is enabled here"
pengguna5071535
sumber
2

Taruh set +xdi dalam tanda kurung, sehingga hanya berlaku untuk lingkup lokal.

Sebagai contoh:

#!/bin/bash -x
exec 3<> /dev/null
(echo foo1 $(set +x)) 2>&3
($(set +x) echo foo2) 2>&3
( set +x; echo foo3 ) 2>&3
true

akan menghasilkan:

$ ./foo.sh 
+ exec
foo1
foo2
foo3
+ true
kenorb
sumber
Perbaiki saya jika saya salah, tetapi saya tidak berpikir bagian set +xdalam subkulit (atau menggunakan subkulit sama sekali) melakukan sesuatu yang bermanfaat. Anda dapat menghapusnya dan mendapatkan hasil yang sama. Ini adalah pengarah stderr ke / dev / null yang melakukan pekerjaan sementara "menonaktifkan" pelacakan ... Sepertinya echo foo1 2>/dev/null, dll, akan sama efektifnya, dan lebih mudah dibaca.
Tyler Rick
Setelah melacak skrip Anda dapat memengaruhi kinerja. Arahan ulang kedua & 2 ke NULL mungkin tidak sama, saat Anda mengharapkan beberapa kesalahan lainnya.
kenorb
Koreksi saya jika saya salah, tetapi dalam contoh Anda, Anda sudah memiliki pelacakan diaktifkan di skrip Anda (dengan bash -x) dan Anda sudah mengarahkan &2ke nol (karena &3dialihkan ke nol), jadi saya tidak yakin bagaimana komentar itu relevan. Mungkin kita hanya perlu contoh yang lebih baik yang mengilustrasikan poin Anda, tetapi dalam contoh yang diberikan setidaknya, sepertinya masih bisa disederhanakan tanpa kehilangan manfaat apa pun.
Tyler Rick
1

Saya suka jawaban yang komprehensif dan dijelaskan dengan baik oleh g-man , dan menganggapnya sebagai jawaban terbaik yang disediakan sejauh ini. Itu peduli dengan konteks skrip, dan tidak memaksa konfigurasi ketika mereka tidak diperlukan. Jadi, jika Anda membaca jawaban ini pertama-tama silakan periksa yang itu, semua manfaat ada di sana.

Namun, dalam jawaban itu ada bagian penting yang hilang: metode yang diusulkan tidak akan berfungsi untuk kasus penggunaan biasa, yaitu melaporkan kesalahan:

COMMAND || echo "Command failed!"

Karena bagaimana alias dikonstruksi, ini akan berkembang menjadi

COMMAND || { save_flags="$-"; set +x; } 2>/dev/null; echo_and_restore "Command failed!"

dan Anda dapat menebaknya, echo_and_restoredieksekusi selalu , tanpa syarat. Mengingat bahwa set +xbagian tersebut tidak berjalan, itu berarti bahwa isi dari fungsi itu akan dicetak juga.

Mengubah yang terakhir ;menjadi &&tidak akan berhasil, karena di Bash, ||dan &&bersifat asosiatif kiri .

Saya menemukan modifikasi yang berfungsi untuk kasus penggunaan ini:

echo_and_restore() {
    echo "$(cat -)"
    case "$save_flags" in
        (*x*) set -x
    esac
}
alias echo='({ save_flags="$-"; set +x; } 2>/dev/null; echo_and_restore) <<<'

Ia menggunakan subshell ( (...)bagian) untuk mengelompokkan semua perintah, dan kemudian meneruskan string input melalui stdin sebagai Here String ( <<<benda) yang kemudian dicetak oleh cat -. Ini -opsional, tetapi Anda tahu, " eksplisit lebih baik daripada implisit ".

Anda juga dapat menggunakan cat -secara langsung tanpa echo , tapi saya suka cara ini karena memungkinkan saya untuk menambahkan string lain ke output. Sebagai contoh, saya cenderung menggunakannya seperti ini:

BASENAME="$(basename "$0")"  # Complete file name
...
echo "[${BASENAME}] $(cat -)"

Dan sekarang ia bekerja dengan indah:

false || echo "Command failed"
> [test.sh] Command failed
j1elo
sumber
0

Jejak eksekusi pergi ke stderr, filter dengan cara ini:

./script.sh 2> >(grep -v "^+ echo " >&2)

Beberapa penjelasan, langkah demi langkah:

  • stderr diarahkan ... - 2>
  • ... untuk suatu perintah. ->(…)
  • grep adalah perintahnya ...
  • ... yang membutuhkan awal dari garis ... - ^
  • ... untuk diikuti oleh + echo...
  • ... lalu grepbalikkan pertandingan ... --v
  • … Dan itu membuang semua baris yang tidak Anda inginkan.
  • Hasilnya biasanya pergi ke stdout; kami mengarahkannya ke stderrtempat yang seharusnya. ->&2

Masalahnya adalah (saya kira) solusi ini dapat melakukan sinkronisasi sinkronisasi aliran. Karena penyaringan stderrmungkin sedikit terlambat dalam kaitannya dengan stdout(di mana echooutput milik default). Untuk memperbaikinya, Anda dapat bergabung dengan stream terlebih dahulu jika Anda tidak keberatan memiliki keduanya di stdout:

./script.sh > >(grep -v "^+ echo ") 2>&1

Anda dapat membangun pemfilteran seperti itu ke dalam skrip itu sendiri tetapi pendekatan ini rentan terhadap desinkronisasi untuk memastikan (mis. Itu telah terjadi dalam pengujian saya: jejak eksekusi perintah mungkin muncul setelah output segera mengikuti echo).

Kode terlihat seperti ini:

#!/bin/bash -x

{
 # original script here
 # …
} 2> >(grep -v "^+ echo " >&2)

Jalankan tanpa trik:

./script.sh

Sekali lagi, gunakan > >(grep -v "^+ echo ") 2>&1untuk mempertahankan sinkronisasi dengan biaya bergabung dengan stream.


Pendekatan lain. Anda mendapatkan "sedikit berlebihan" dan output yang tampak aneh karena terminal Anda bercampur stdoutdanstderr . Kedua aliran ini adalah binatang yang berbeda karena suatu alasan. Periksa apakah analisis stderrhanya sesuai dengan kebutuhan Anda; buang stdout:

./script.sh > /dev/null

Jika Anda memiliki skrip echodebug pesan pencetakan / kesalahan untuk stderrmaka Anda dapat menghilangkan redundansi dengan cara yang dijelaskan di atas. Perintah penuh:

./script.sh > /dev/null 2> >(grep -v "^+ echo " >&2)

Kali ini kami hanya bekerja dengan stderr, jadi desinkronisasi tidak lagi menjadi perhatian. Sayangnya dengan cara ini Anda tidak akan melihat jejak atau keluaran dari echocetakan itu untuk stdout(jika ada). Kita bisa mencoba untuk membangun kembali filter kami untuk mendeteksi pengalihan ( >&2) tetapi jika Anda melihat echo foobar >&2, echo >&2 foobardan echo "foobar >&2"kemudian Anda mungkin akan setuju bahwa semakin banyak masalah.

Banyak tergantung pada gema yang Anda miliki dalam skrip Anda. Berpikir dua kali sebelum Anda menerapkan beberapa filter kompleks, mungkin akan menjadi bumerang. Lebih baik memiliki sedikit redundansi daripada secara tidak sengaja melewatkan beberapa informasi penting.


Alih-alih membuang jejak eksekusi echokita dapat membuang outputnya - dan output apa pun kecuali jejak. Untuk menganalisis jejak eksekusi saja, coba:

./script.sh > /dev/null 2> >(grep "^+ " >&2)

Sangat mudah? Tidak. Pikirkan apa yang akan terjadi jika ada echo "+ rm -rf --no-preserve-root /" >&2dalam naskah. Seseorang mungkin terkena serangan jantung.


Dan akhirnya…

Untungnya ada BASH_XTRACEFDvariabel lingkungan. Dari man bash:

BASH_XTRACEFD
Jika disetel ke bilangan bulat yang terkait dengan deskriptor file yang valid, bash akan menulis output jejak yang dihasilkan saat set -xdiaktifkan ke deskriptor file tersebut.

Kita bisa menggunakannya seperti ini:

(exec 3>trace.txt; BASH_XTRACEFD=3 ./script.sh)
less trace.txt

Perhatikan baris pertama memunculkan subkulit. Dengan cara ini deskriptor file tidak akan tetap valid atau variabel yang ditugaskan di shell saat ini setelahnya.

Berkat BASH_XTRACEFDAnda dapat menganalisis jejak yang bebas dari gema dan output lainnya, apa pun itu. Ini tidak persis seperti yang Anda inginkan tetapi analisis saya membuat saya berpikir ini (secara umum) The Right Way.

Tentu saja Anda dapat menggunakan metode lain, terutama saat Anda perlu menganalisis stdoutdan / atau stderrmengikuti jejak Anda. Anda hanya perlu mengingat ada batasan dan jebakan tertentu. Saya mencoba menunjukkan kepada mereka.

Kamil Maciorowski
sumber
0

Dalam Makefile Anda bisa menggunakan @simbol.

Contoh penggunaan: @echo 'message'

Dari dokumen GNU ini :

Ketika sebuah baris dimulai dengan '@', gema dari baris itu ditekan. '@' Dibuang sebelum garis dilewatkan ke shell. Biasanya Anda akan menggunakan ini untuk perintah yang efeknya hanya untuk mencetak sesuatu, seperti perintah gema untuk menunjukkan kemajuan melalui makefile.

derek
sumber
Hai, dokumen yang Anda rujuk adalah untuk gnu make, bukan shell. Apakah Anda yakin itu berhasil? Saya mendapatkan kesalahan ./test.sh: line 1: @echo: command not found, tapi saya menggunakan bash.
Wow, maaf saya salah membaca pertanyaan. Ya, @hanya berfungsi saat Anda bergaung di makefile.
derek
@derek Saya mengedit balasan asli Anda sehingga sekarang dengan jelas menyatakan bahwa solusinya terbatas untuk Makefiles saja. Saya sebenarnya mencari yang ini, jadi saya ingin komentar Anda tidak memiliki reputasi negatif. Semoga, orang-orang akan merasakan manfaatnya juga.
Shakaron
-1

Diedit 29 Okt 2016 per saran moderator bahwa yang asli tidak mengandung informasi yang cukup untuk memahami apa yang terjadi.

"Trik" ini menghasilkan hanya satu baris output pesan di terminal ketika xtrace aktif:

Pertanyaan aslinya adalah Apakah ada cara untuk membiarkan -x diaktifkan, tetapi hanya menampilkan pesan alih-alih dua baris . Ini adalah sebuah kutipan tepat dari pertanyaan.

Saya mengerti pertanyaannya, bagaimana "membiarkan set -x diaktifkan DAN menghasilkan satu baris untuk sebuah pesan"?

  • Dalam arti global, pertanyaan ini pada dasarnya adalah tentang estetika - si penanya ingin menghasilkan satu baris alih-alih dua duplikat yang sebenarnya garis yang dihasilkan saat xtrace aktif.

Jadi secara ringkas, OP membutuhkan:

  1. Memiliki set -x berlaku
  2. Menghasilkan pesan, dapat dibaca manusia
  3. Hanya menghasilkan satu baris output pesan.

OP tidak mengharuskan perintah gema digunakan. Mereka mengutipnya sebagai contoh produksi pesan, menggunakan singkatan mis Yang merupakan singkatan dari Latin exempli gratia, atau "misalnya".

Berpikir "di luar kotak" dan mengabaikan penggunaan gema untuk menghasilkan pesan, saya perhatikan bahwa pernyataan tugas dapat memenuhi semua persyaratan.

Lakukan penugasan string teks (berisi pesan) ke variabel tidak aktif.

Menambahkan baris ini ke skrip tidak mengubah logika apa pun, namun menghasilkan satu baris saat tracing aktif: (Jika Anda menggunakan variabel $ echo , cukup ubah nama menjadi variabel lain yang tidak digunakan)

echo="====================== Divider line ================="

Apa yang akan Anda lihat di terminal hanya 1 baris:

++ echo='====================== Divider line ================='

bukan dua, karena OP tidak suka:

+ echo '====================== Divider line ================='
====================== Divider line =================

Berikut ini contoh skrip untuk ditunjukkan. Perhatikan bahwa penggantian variabel ke dalam pesan (nama direktori $ HOME 4 baris dari akhir) berfungsi, sehingga Anda dapat melacak variabel menggunakan metode ini.

#!/bin/bash -exu
#
#  Example Script showing how, with trace active, messages can be produced
#  without producing two virtually duplicate line on the terminal as echo does.
#
dummy="====================== Entering Test Script ================="
if [[ $PWD == $HOME ]];  then
  dummy="*** "
  dummy="*** Working in home directory!"
  dummy="*** "
  ls -la *.c || :
else
  dummy="---- C Files in current directory"
  ls -la *.c || :
  dummy="----. C Files in Home directory "$HOME
  ls -la  $HOME/*.c || :
fi

Dan ini adalah output dari menjalankannya di root, lalu direktori home.

$ cd /&&DemoScript
+ dummy='====================== Entering Test Script ================='
+ [[ / == /g/GNU-GCC/home/user ]]
+ dummy='---- C Files in current directory'
+ ls -la '*.c'
ls: *.c: No such file or directory
+ :
+ dummy='----. C Files in Home directory /g/GNU-GCC/home/user'
+ ls -la /g/GNU-GCC/home/user/HelloWorld.c /g/GNU-GCC/home/user/hw.c
-rw-r--r-- 1 user Administrators 73 Oct 10 22:21 /g/GNU-GCC/home/user/HelloWorld.c
-rw-r--r-- 1 user Administrators 73 Oct 10 22:21 /g/GNU-GCC/home/user/hw.c
+ dummy=---------------------------------

$ cd ~&&DemoScript
+ dummy='====================== Entering Test Script ================='
+ [[ /g/GNU-GCC/home/user == /g/GNU-GCC/home/user ]]
+ dummy='*** '
+ dummy='*** Working in home directory!'
+ dummy='*** '
+ ls -la HelloWorld.c hw.c
-rw-r--r-- 1 user Administrators 73 Oct 10 22:21 HelloWorld.c
-rw-r--r-- 1 user Administrators 73 Oct 10 22:21 hw.c
+ dummy=---------------------------------
HiTechHiTouch
sumber
1
Catatan, bahkan versi yang sudah diedit dari jawaban Anda yang dihapus (yang merupakan salinan), tetap tidak menjawab pertanyaan, karena jawabannya tidak hanya menampilkan pesan tanpa perintah gema yang terkait, yang merupakan apa yang diminta OP.
DavidPostill
Catatan, jawaban ini sedang dibahas pada meta. Apakah saya telah dihukum karena jawaban yang tidak disukai moderator?
DavidPostill
@ David Saya telah memperbesar penjelasannya, per komentar di forum meta.
HiTechHiTouch
@ Bersihkan Lagi Saya mendorong Anda untuk membaca OP dengan sangat hati-hati, memperhatikan bahasa Latin ".eg". Poster TIDAK mengharuskan perintah gema digunakan. Referensi OP hanya menggemakan sebagai contoh (bersama dengan redirection) metode potensial untuk memecahkan masalah. Ternyata Anda tidak perlu,
HiTechHiTouch
Dan bagaimana jika OP ingin melakukan sesuatu seperti echo "Here are the files in this directory:" *?
G-Man Mengatakan 'Reinstate Monica'