Yankı komutu için yürütme izini engelle?


29

Shebang seçenekleriyle Shell Script'leri başlatan Jenkins'den Shell Script'leri çalıştırıyorum #!/bin/sh -ex.

Aptallar için Bash Shebang'a göre mi? ,, -x"kabuğun bir yürütme izi yazdırmasına neden oluyor", bu, çoğu amaç için harika olan - echos hariç:

echo "Message"

çıktı üretir

+ echo "Message"
Message

Bu biraz gereksiz ve biraz garip görünüyor. -xEtkin bırakmanın bir yolu var , ancak yalnızca çıktı

Message

yukarıdaki iki satır yerine, örneğin echo komutunu özel bir komut karakteriyle ön ekleyerek veya çıkışı yönlendirerek mi?

Yanıtlar:


20

Timsahlarda boynunuza kalktığınızda, amacın bataklığı boşaltmak olduğunu unutmak kolaydır.                   - popüler söyleyerek

Sorun şu an hakkında echove henüz cevapların çoğunluğu bir set +xkomutu nasıl gizlice sokacağımıza odaklandı . Çok daha basit ve daha doğrudan bir çözüm var:

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

(Daha { …; } 2> /dev/null önceki cevaplarda görmemiş olup olmadığımı düşünmemiş olabileceğimi kabul ediyorum .)

Bu biraz hantaldır, ancak ardışık echokomutlar bloğunuz varsa , bunu her biri için ayrı ayrı yapmanız gerekmez:

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

Yeni çizgileriniz olduğunda noktalı virgül kullanmanıza gerek olmadığını unutmayın.

Sen kullanarak yazarak yükünü azaltabilir kenorb fikrini açma /dev/nullstandart olmayan bir dosya tanımlayıcı üzerinde kalıcı (örneğin 3) ve daha sonra söyleyerek 2>&3yerine 2> /dev/nullher zaman.


Bu yazının yazıldığı anda ilk dört cevaplar (çoğu durumda, hantal içinde ve) özel bir şey yapıyor gerektiren her bir yapmak zaman echo. Eğer gerçekten tüm echo komutların yürütme izini bastırmasını istiyorsanız (ve neden olmasın?), Çok fazla kod sarsmadan bunu global olarak yapabilirsiniz. İlk olarak, takma adların izlenemediğini fark ettim:

$ 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

(Shebang, bash bağlantısı #!/bin/sholsa bile , aşağıdaki betiğin snippet'lerinin işe yaradığını unutmayın /bin/sh. Ancak, eğer shebang ise #!/bin/bash, shopt -s expand_aliasestakma adın bir komut dosyasında çalışmasını sağlamak için bir komut eklemeniz gerekir .)

Yani ilk numaram için:

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

Şimdi, söylediğimizde echo "Message"takma ismini arıyoruz, ki bu izlenmiyor. Diğer ad, izleme mesajını setkomuttan gizleyerek ( önce user5071535'in cevabında sunulan tekniği kullanarak ) izlemeyi kapatır ve sonra gerçek echokomutu çalıştırır . Bu, her echo komutta kodu düzenlemeye gerek kalmadan kullanıcı5071535'in cevabına benzer bir etki elde etmemizi sağlar . Ancak, bu izleme modunu kapalı bırakır. Bir set -xtakma adı koyamayız (veya en azından kolayca değil) çünkü takma ad yalnızca bir dize bir sözcüğün yerine kullanılmasına izin verir; takma ismin dizisinin hiçbir kısmı argümanlardan sonra komuta enjekte edilemez (örn "Message".). Örneğin, komut dosyası içeriyorsa

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

çıktı

+ 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

bu nedenle, ileti (ler) i görüntüledikten sonra izleme seçeneğini tekrar açmanız gerekir - ancak ardışık her komut bloğundan sonra yalnızca bir kez echo:

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


Biraz set -xsonra echohile yaparak otomatikleştirmeyi başarırsak iyi olurdu . Fakat bunu sunmadan önce bunu düşünün. OP, bir #!/bin/sh -exshebang kullanan senaryolarla başlıyor . Örtülü olarak kullanıcı kullanıcıyı xshebang'dan kaldırabilir ve yürütme izlemesi olmadan normal şekilde çalışan bir komut dosyasına sahip olabilir. Bu özelliği koruyan bir çözüm geliştirebilseydik daha iyi olurdu. Buradaki ilk birkaç cevap, bu özellikten başarısız oldu çünkü echozaten açık olup olmadığına bakılmaksızın koşulsuz olarak ifadelerden sonra “geriye” doğru izlemeye başladılar .  Bu cevap dikkat çekici bir şekilde bu konuyu değiştirmekte başarısız oluyor echoiz çıkışı ile çıktı; bu nedenle, izleme kapatıldığında tüm mesajlar kaybolur. Şimdi koşullu bir echoifadeden sonra geriye dönüş yapan bir çözüm sunacağım - sadece açıksa. Bunu koşulsuz olarak “geri” izleyen bir çözüme indirgemek önemsizdir ve bir egzersiz olarak bırakılır.

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
}

$-seçenekler listesi; ayarlanan tüm seçeneklere karşılık gelen harflerin birleştirilmesi. Örneğin, eve xseçenekleri ayarlanmışsa, o $-zaman eve içeren harflerin bir kargaşası olacaktır x. Yeni takma adım (üstte) $-izlemeyi kapatmadan önce değerini korur. Ardından, izleme kapalıyken kontrolü bir kabuk fonksiyonuna atar. Bu işlev gerçek olanı yapar ve diğer ad çağrıldığında seçeneğin açık echo olup olmadığını kontrol eder x. Seçenek açıksa, işlev tekrar açar; kapalıysa, işlev onu bırakır.

shoptSenaryonun başına yukarıdaki yedi satırı (eğer varsa, sekiz) ekleyebilir ve gerisini yalnız bırakabilirsiniz.

Bu sana izin verecek

  1. Aşağıdaki shebang hatlarından herhangi birini kullanmak için:
    #! / bin / sh -ex
    #! / bin / sh -e
    #! / bin / sh –x
    ya da sadece düz
    #! / Bin / sh
    ve beklendiği gibi çalışması gerekir.
  2. koduna sahip olmak
    (shebang) 
    komut 1
     komut 2
     komut 3
    -x ayarla
    komut 4
     komut 5
     komut 6
    + x ayarla
    komut 7
     komut 8
     komut 9
    ve
    • Komutlar 4, 5 ve 6 izlenecek - bunlardan biri bir değilse echo, bu durumda uygulanacak ancak izlenmeyecektir. (Ancak komut 5 bir olsa bile echo, komut 6 hala izlenecektir.)
    • Komutlar 7, 8 ve 9 izlenmeyecek. Komut 8 bir an olsa bile echo, komut 9 hala izlenmeyecektir.
    • 1, 2 ve 3 komutları, Shebang'ın içerip içermediğine bağlı olarak izlenecek (4, 5 ve 6 gibi) veya olmayacak (7, 8 ve 9 gibi) x.

PS: Sistemimde, builtinanahtar kelimeyi orta cevabımda (sadece takma ad için olan echo) dışlayabileceğimi öğrendim . Bu şaşırtıcı değil; bash (1), takma ad genişletmesi sırasında…

… Genişletilen diğer adıyla aynı olan bir kelime ikinci kez genişletilmez. Bir takma adlı olabileceğini Bu araçlar lsiçin ls -F, örneğin, ve bash yinelemeli yedek metni genişletmek için çalışmaz.

Çok da şaşırtıcı olmayan bir şekilde, anahtar kelime 1 girilmezse , son cevap (cevap veren echo_and_restore) başarısız olur . Ancak, silerek ve sırasını değiştirirseniz garip bir şekilde çalışır :builtinbuiltin

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  Tanımlanmamış davranışa yol açıyor gibi görünüyor. gördüm

  • sonsuz bir döngü (muhtemelen sınırlandırılmamış özyineleme nedeniyle),
  • bir /dev/null: Bad addresshata mesajı ve
  • Bir çekirdek dökümü.

2
Takma adlarla yapılan bazı sihirli hileler gördüm, bu yüzden bilgilerimin eksik olduğunu biliyorum. Herhangi biri echo +x; echo "$*"; echo -xbir takma adın eşdeğerini yapmanın bir yolunu sunabilirse , onu görmek isterim.
G-Man

11

InformIT'te kısmi bir çözüm buldum :

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

çıktılar

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

Ne yazık ki, bu hala yankılanıyor set +x, ama en azından ondan sonra sessiz. bu yüzden sorun en azından kısmi bir çözüm.

Ama bunu yapmanın daha iyi bir yolu var mı? :)


2

Bu sayede set +xçıktıdan kurtularak kendi çözümünüzü geliştirebilirsiniz :

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

2

set +xKöşeli parantezin içine koyun , sadece yerel alan için geçerli olacaktır.

Örneğin:

#!/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

çıktı:

$ ./foo.sh 
+ exec
foo1
foo2
foo3
+ true

Yanılıyorsam düzelt beni, ama set +xalt kabuğun içinde (ya da hiç alt kabukları kullanarak) işe yarar bir şey yaptığını düşünmüyorum . Bunu kaldırabilir ve aynı sonucu elde edebilirsiniz. Bu, geçici olarak "devre dışı bırakma" izlemesini gerçekleştiren stderr'i / dev / null'a yönlendiriyor ... Görünüşe göre echo foo1 2>/dev/null, bu kadar etkili ve daha okunaklı görünüyor.
Tyler Rick,

Komut dosyanızda izlemeye sahip olmak performansı etkileyebilir. İkincisi & 2'den NULL'a yönlendirmek, başka bir hata beklediğinizde aynı olmayabilir.
kenorb

Hatalıysam beni düzelt, ancak örneğinde betiğinde (with bash -x) etkin izlemeyi zaten kullandın ve zaten null'a yönlendiriliyorsun &2(null'a &3yönlendirildiğinden), bu yüzden bu yorumun ne kadar alakalı olduğundan emin değilim. Belki de amacınızı açıklayan daha iyi bir örneğe ihtiyacımız var, ancak verilen örnekte en azından herhangi bir fayda kaybetmeden basitleştirilmiş gibi görünüyor.
Tyler Rick,

1

Ben g-man'ın kapsamlı ve iyi açıklanmış cevabını seviyorum ve şimdiye kadar sağlanan en iyisini düşünüyorum. Komut dosyasının içeriğiyle ilgilenir ve gerekmediğinde yapılandırmaları zorlamaz. Yani, eğer bu cevabı okuyorsanız, ilk önce devam edin ve bir cevap verin, tüm hak var orada.

Bununla birlikte, bu cevapta önemli bir parça eksiktir: önerilen yöntem tipik bir kullanım durumu için işe yaramaz, yani hataları bildirir:

COMMAND || echo "Command failed!"

Diğer adın nasıl oluşturulduğuna bağlı olarak,

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

ve tahmin ettin , koşulsuz olarak her zamanecho_and_restore idam edilir . Parçanın çalışmadığı göz önüne alındığında , bu işlevin içeriğinin de yazdırılacağı anlamına gelir.set +x

Geçen değiştirme ;için &&çünkü Bash, da işe, olmaz ||ve &&olan sol-ilişkisel .

Bu kullanım durumu için işe yarayan bir değişiklik buldum:

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) <<<'

(...)Tüm komutları gruplamak için bir alt kabuk ( bölüm) kullanır ve daha sonra tarafından basılan bir Here String ( giriş) olarak stdin içinden giriş dizesini geçirir . Bu isteğe bağlıdır, ancak “ açık, örtükten daha iyidir ”.<<<cat --

cat -Doğrudan eko olmadan da kullanabilirsiniz , ancak bu şekilde hoşuma gidiyor, çünkü çıktıya başka dizeler eklememe izin veriyor. Örneğin, bu şekilde kullanma eğilimindedir:

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

Ve şimdi güzel çalışıyor:

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

0

İcra takibi stderrşu şekilde gider :

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

Bazı açıklamalar, adım adım:

  • stderr yönlendirildi… - 2>
  • … Bir komuta. ->(…)
  • grep emirdir…
  • … Bu, hattın başlangıcını gerektirir… - ^
  • … Takip edecek + echo
  • … Sonra grepmaçı tersine çevirir… --v
  • … Ve istemediğiniz tüm çizgileri atar.
  • Sonuç normalde giderdi stdout; stderrait olduğu yere yönlendiririz . ->&2

Sorun şu ki (sanırım) bu çözüm akışları zaman uyumsuz hale getirebilir. Filtreleme nedeniyle ( çıkış varsayılan olarak ait olduğu stderr) ile ilgili olarak biraz geç olabilir . Düzeltmek için önce ikisine de sahip olmanız sakıncası yoksa ilk önce akışlara katılabilirsiniz :stdoutechostdout

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

Senaryoya böyle bir filtreleme oluşturabilirsiniz, ancak bu yaklaşım kesin olarak zaman uyumsuzluğa açıktır (yani testlerimde gerçekleşti: bir komutun yürütme izi hemen izleyen çıktıdan sonra görünebilir echo).

Kod şöyle gözüküyor:

#!/bin/bash -x

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

Hiçbir numara yapmadan koş:

./script.sh

Yine, > >(grep -v "^+ echo ") 2>&1senkronizasyonu akışlara katılma pahasına tutmak için kullanın .


Başka bir yaklaşım. "Biraz yedekli" ve tuhaf görünümlü çıktılar elde edersiniz, çünkü terminaliniz karıştırır stdoutvestderr . Bu iki akım bir nedenden dolayı farklı hayvanlardır. Analizin stderryalnızca ihtiyaçlarınızı karşılayıp karşılamadığını kontrol edin ; at stdout:

./script.sh > /dev/null

Komut dosyanızda echoyazdırılacak bir hata ayıklama / hata mesajı stderrvarsa, yukarıda açıklanan şekilde yedeklilikten kurtulabilirsiniz. Tam komut:

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

Bu sefer stderrsadece çalıştığımız için senkronizasyon artık bir endişe değil. Ne yazık ki bu şekilde (varsa) echoyazdırılan izden veya çıktısı görmezsiniz stdout. Biz yeniden yönlendirme (algılamak için bizim filtreyi yeniden deneyebilirsiniz >&2) ama bakarsanız echo foobar >&2, echo >&2 foobarve echo "foobar >&2"o zaman bu işler karışmaya muhtemelen kabul edecektir.

Çok şey, senaryolarınızdaki ekolara bağlıdır. Bazı karmaşık filtreleri uygulamadan önce iki kez düşünün, geri tepebilir. Yanlışlıkla önemli bir bilgiyi yanlışlıkla kaçırmamaktan biraz fazlalık olması daha iyidir.


Bir işlemin izini echosilmek yerine, bir çıktısını - izleri dışında herhangi bir çıktısını - atabiliriz. Yalnızca yürütme izlerini analiz etmek için şunu deneyin:

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

Kusursuz? Hayır echo "+ rm -rf --no-preserve-root /" >&2. Senaryoda yazılırsa ne olacağını bir düşün . Birileri kalp krizi geçirebilir.


Ve sonunda…

Neyse ki BASH_XTRACEFDçevresel değişken var. Kimden man bash:

BASH_XTRACEFD
Geçerli bir dosya tanımlayıcısına karşılık gelen bir tamsayıya ayarlanırsa, bash, set -xbu dosya tanımlayıcısına etkinleştirildiğinde oluşturulan izleme çıktısını yazacaktır .

Bunu böyle kullanabiliriz:

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

İlk satırın bir alt kabuk ortaya çıktığını unutmayın. Bu şekilde, dosya tanımlayıcısı geçerli kalamaz ya da sonradan geçerli kabuğa atanan değişken.

Teşekkürler BASH_XTRACEFD, her ne olursa olsun, yankı ve diğer çıktılardan arındırılmış izleri analiz edebilirsiniz. Tam olarak istediğin bu değil ama analizim bunun (genel olarak) Doğru Yol olduğunu düşündürmemi sağlıyor.

Elbette, özellikle izlerinizi analiz etmeniz stdoutve / veya stderrbirlikte izlemeniz gerektiğinde başka bir yöntem kullanabilirsiniz . Sadece bazı sınırlamalar ve tuzaklar olduğunu hatırlamanız gerekir. Bazılarını göstermeye çalıştım.


0

Bir Makefile'da @sembolü kullanabilirsiniz .

Örnek Kullanım: @echo 'message'

Gönderen bu GNU doc:

Bir çizgi '@' ile başladığında, bu çizginin yankısı bastırılır. Satır kabuğa geçirilmeden önce '@' atılır. Genelde bunu, tek etkisi makefile'deki ilerlemeyi belirtmek için echo komutu gibi bir şeyi yazdırmak olan komut için kullanırsınız.


Merhaba, referansta bulunduğunuz doktor gnu yapmak içindir, kabuk değildir. İşe yaradığından emin misin? Hata alıyorum ./test.sh: line 1: @echo: command not found, ancak bash kullanıyorum.

Vay, üzgünüm soruyu tamamen yanlış anladım. Evet, @yalnızca makefiles'te yankılanırken çalışır.
derek

@ derek Orijinal cevabınızı düzenlemiştim, bu yüzden şimdi çözümün yalnızca Makefiles için sınırlı olduğunu açıkça belirtiyorum. Aslında bunu arıyordum, bu yüzden yorumunuzun olumsuz bir üne sahip olmamasını istedim. Umarım, insanlar da bunu yararlı bulur.
Shakaron

-1

Moderatör başına 29 Eki 2016 tarihinde düzenlendi, orijinal olanın ne olduğunu anlamak için yeterli bilgi içermediğini öne sürdü.

Bu "hile", xtrace etkinken terminalde yalnızca bir satır çıktı satırı üretir:

Orijinal soru şudur: -x etkin bırakmanın bir yolu var, ancak iki satır yerine yalnızca İleti çıktısını alın . Bu sorudan kesin bir alıntı.

"Set -x'i etkin bırakmak ve bir mesaj için tek bir satır üretmek" şeklinde bir soruyu anlıyorum.

  • Küresel anlamda, bu soru temel olarak estetik ile ilgilidir - sorgulayıcı , xtrace aktifken üretilen neredeyse iki kopya satır yerine tek bir satır üretmek istiyor .

Özetle, OP'nin gerektirdiği:

  1. Sahip olmak set -x yürürlükte
  2. İnsan tarafından okunabilen bir mesaj üret
  3. Yalnızca tek bir mesaj çıktısı satırı üretir.

OP yok değil gerektirir yankı komutu kullanılabilir. Bunlar, olarak anılan , örneğin kısaltması kullanılarak, mesaj üretiminin , örneğin , ya da "örneğin" Latin örneklendiği gratia anlamına gelir.

"Kutunun dışında" olduğunu ve mesaj üretmek için yankı kullanımını bıraktığını düşünüyorum , bir atama ifadesinin tüm gereklilikleri yerine getirebileceğini unutmayın.

Etkin olmayan bir değişkene bir metin dizgisi (iletiyi içeren) atayın.

Bu satırı bir komut dosyasına eklemek herhangi bir mantığı değiştirmez, ancak izleme etkin olduğunda tek bir satır oluşturur: ( $ echo değişkenini kullanıyorsanız , adı yalnızca kullanılmayan bir değişkenle değiştirin)

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

Terminalde göreceğiniz şey sadece 1 satır:

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

OP beğenmediği için iki değil:

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

İşte göstermek için örnek komut dosyası. Bir mesaja değişken değişiminin ($ HOME dizin adı sondan 4 satır) işe yarıyor, bu yöntemi kullanarak değişkenleri takip edebilirsiniz.

#!/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

Ve işte kök, sonra da ana dizinde çalıştırmanın sonucu.

$ 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=---------------------------------

1
Not: Silinen cevabınızın düzenlenmiş versiyonunun bile (ki bunun bir kopyası), cevabın OP'nin istediği gibi, sadece yankı sadece bir yankı komutu olmadan gelen mesajı vermediği için hala soruya cevap vermiyor.
DavidPostill


@David Meta forumdaki açıklamalara göre açıklamayı genişlettim.
HiTechHiTouch 4

@David Yine, Latince ".eg" ye dikkat ederek OP'yi dikkatlice okumanızı tavsiye ediyorum. Poster, echo komutunun kullanılmasını gerektirmez. OP sadece sorunu çözmek için olası yöntemlerin bir örneği olarak (yeniden yönlendirme ile birlikte) ekoyu referans alır .
İkinize

Peki ya OP böyle bir şey yapmak isterse echo "Here are the files in this directory:" *?
G-Man
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.