Jalankan sebagai .test daripada ./test


26

Andaikata saya berada di folder yang sama dengan file yang dapat dieksekusi, saya perlu mengetik ini untuk menjalankannya:

./file

Saya lebih suka tidak perlu mengetik /, karena /sulit bagi saya untuk mengetik.

Apakah ada cara yang lebih mudah untuk mengeksekusi file? Idealnya hanya beberapa sintaks sederhana seperti:

.file

atau sesuatu yang lain tetapi lebih mudah daripada harus memasukkan /karakter di sana.

Mungkin ada beberapa cara untuk meletakkan sesuatu di /bindirektori, atau membuat alias untuk penerjemah, sehingga saya bisa menggunakan:

p file

9
Mungkin swap / dengan kunci lain menggunakan xmodmap? Jadi setidaknya lebih mudah untuk mengetik
Guy

26
Sebagai catatan, /digunakan secara luas di Unix, sebagian besar sebagai pemisah direktori. Anda mungkin lebih baik menemukan cara yang lebih mudah untuk mengetiknya.
chrylis -pada mogok-

7
@RossPresser Pertanyaan ini sangat tidak masuk akal sejak itu. dan ./ di awal file adalah dua arti yang sangat berbeda karena alasan teknis yang harus diketahui oleh pemula. /tidak sulit untuk mengetik untuk sebagian besar orang, dan jika OP memiliki cedera yang mencegah hal ini, mereka harus mempertimbangkan tata letak keyboard alternatif, karena tidak ada cara mereka dapat menghindari /sepenuhnya saat berada di terminal.
JFA

1
@JFA Mayoritas layout keyboard yang digunakan di benua Eropa dan juga Amerika Selatan memakai /shift-7 yang relatif sulit untuk diketik , bahkan tanpa cedera.
nitro2k01

6
Edit riwayat: " mengapa tidak bisa Antarmuka Jaringan diinstruksikan secara sederhana untuk membuat semua permintaan internet melalui host jarak jauh melalui ssh pada port 22. " ಠ_ಠ
Derek 朕 會 功夫

Jawaban:


35

Ini bisa "berisiko" tetapi Anda bisa saja melakukannya. di PATH Anda.

Seperti yang telah dikatakan pada orang lain, ini bisa berbahaya jadi selalu pastikan. lebih pada akhir PATH daripada awal.


1
Jangan benar-benar melihat bagaimana itu "berisiko": jalan saya telah seperti itu sejak lama sebelum linux, dan itu tidak pernah menyebabkan masalah sekecil apa pun.
jamesqf

21
@ jamesqf Berisiko karena jika Anda cdke direktori yang dapat ditulis oleh dunia dan mencoba menggunakan perintah yang tidak ada di jalur Anda, Anda dapat menjalankan (mungkin berbahaya) yang dapat dieksekusi dengan nama yang sama dengan yang ditulis seseorang ke jalur itu. Ini jauh lebih buruk jika Anda meletakkannya .di awal jalan Anda. Dalam hal itu, eksekusi berbahaya yang dipanggil lsakan dieksekusi jika Anda mencoba memanggil lsdirektori itu.
bytesized

2
Harap hindari ini, untuk alasan yang ditentukan di atas. The pperintah akan lebih baik.
Guido

11
@ jamesqf Saat itu adalah sistem "Anda", dan hanya Anda yang menggunakannya, itu tidak terlalu buruk. Masalahnya muncul (dan telah membuat banyak admin Unix selama bertahun-tahun) pada sistem multi-pengguna. Dengan .awal PATH, semua yang perlu dilakukan pengguna jahat adalah menjatuhkan lsperintah palsu di direktori mereka dan membujuk admin untuk "melihat sesuatu yang aneh" dan mereka punya akses root.
TripeHound

1
Solusi yang bagus, meskipun itu tidak akan berfungsi jika file tersebut dinamai test, seperti dalam judul pertanyaan (karena testini adalah built-in shell, dan mungkin juga sudah ada di suatu tempat di Anda $PATHsudah).
yellowantphil

71

.akan secara otomatis melengkapi./ (mengetik .dan menekan Tab) setidaknya di shell Bash modern, jadi Anda tidak perlu menggunakan solusi yang kompleks atau tidak aman (seperti PATHmodifikasi).

Jika tidak lengkap secara otomatis, Anda mungkin perlu menginstal paket "bash-completion".


Apakah kamu yakin .memiliki beberapa kandidat penyelesaian: .(direktori saat ini), ..(direktori induk), .perintah (yang disediakan bash sourceuntuk alias tidak standar ), dan semua dotfile yang ada. Mungkin bash-completionpaket mengabaikan ini; Saya merasa itu sangat menjengkelkan (mis. Membuatnya tidak mungkin untuk melabeli nama dir pada makebaris perintah dan umumnya buruk dengan makefile yang penuh dengan aturan implisit) jadi saya selalu membersihkannya.
R ..

3
Saya sudah mencobanya, dan ya, memang lengkap dengan cara ini. Dalam hampir setiap kasus itulah yang diinginkan oleh pengguna biasa: Saya rasa saya belum pernah melihat dotfile yang harus dieksekusi, menjalankan sesuatu dalam subdirektori jauh lebih umum daripada menjalankan sesuatu di direktori induk, dan IMO melakukannya pekerjaan yang sangat bagus untuk menemukan maketarget.
l0b0

Dengan bash 3.2 tidak lengkap secara otomatis. Mungkinkah ini baru di bash 4?
Calimo

2
@ Calimo Lebih mungkin baru di versi terbaru dari penyelesaian-bash. Jauh dari perubahan mendasar.
l0b0

42

atau .. mungkin memberi penerjemah alias dalam file bashrc dan kemudian secara sederhana

   p  file

Dimungkinkan untuk menulis fungsi seperti itu:

p() {
 ./"$@"
}

di Anda ~/.bashrc. Maka Anda akan dapat menjalankan p app argumentsalih-alih ./app arguments. Solusi ini berfungsi untuk jenis apa pun yang dapat dieksekusi, termasuk skrip dan binari.

"$@"meluas ke daftar argumen yang dikutip dengan tepat yang diteruskan ke fungsi (mempertahankan semua karakter khusus dari gumpalan atau ekspansi variabel), dan, seperti yang ditunjukkan @Scott, bashcukup pintar untuk bergantung ./pada yang pertama, menjaga sisanya.


Meskipun kurang umum untuk menjalankan aplikasi di bawah perintah lain, suka strace -f p appmelihat panggilan sistem dibuat, atau $(which time) p appuntuk melihat berapa lama. psebagai skrip yang dapat dieksekusi akan bekerja lebih baik dalam dua contoh spesifik yang saya buat. Tidak ada solusi yang dapat bekerja ldd p app, meskipun ldd juga berbeda dalam membutuhkan jalur penuh, mungkin karena alasan seperti ini.
sourcejedi

Ya, mengganti p app argsdengan ./app argscara yang tidak terlihat oleh siapa pun akan membutuhkan input shell piping melalui semacam preprocessor dan akan menyebabkan segala macam kesenangan ketika penggantian terjadi di tempat yang tidak disengaja :)
aitap

1
Dalam hal ini, bukankah seharusnya tidak ada tanda kutip di sekitar $@? Kalau tidak, itu hanya akan melewati satu argumen besar ke program.
Kroltan

7
@Kroltan No. $@adalah array. Ketika diperluas dalam ", setiap parameter diperluas ke kata yang terpisah. $*berperilaku seperti yang Anda pikirkan.
8bittree

3
Saya percaya bahwa Anda telah membuat ini menjadi tidak perlu, dan hanya itu p() { ./"$@"; }yang Anda butuhkan.
Scott

11

Anda dapat menempatkan .ke Anda $PATHdengan menambahkan misalnya PATH=$PATH:.ke Anda /etc/profile, dengan cara ini Anda dapat mengeksekusi filehanya dengan menulis file, kecuali itu ada di folder lain di jalur Anda (misalnya /usr/bin/). Perhatikan bahwa ini umumnya bukan ide yang baik.

Mengapa itu buruk: Katakanlah Anda berada dalam situasi di mana Anda tidak sepenuhnya mempercayai isi direktori - Anda telah mengunduhnya dari suatu tempat yang cerdik dan Anda ingin menyelidikinya sebelum menjalankannya, atau Anda seorang sysadmin membantu beberapa pengguna dengan melihat di direktori home mereka, dll. Anda ingin membuat daftar direktori, jadi Anda mencoba mengetik ls, tetapi oops, Anda membuat kesalahan ketik, dan akhirnya mengetikkan sl. Penulis direktori jahat ini mengantisipasi ini dan meletakkan skrip shell di dalamnya yang disebut "sl" yang menjalankan 'rm -rf --no-preserve-root /' (atau sesuatu yang lebih berbahaya seperti memasang rootkit).

(Terima kasih @Muzer untuk penjelasannya)


13
Meskipun aku setuju, itu mungkin menjelaskan mengapa ini bukan ide yang baik.
ymbirtt

16
Mengapa itu buruk: Katakanlah Anda berada dalam situasi di mana Anda tidak sepenuhnya mempercayai isi direktori - Anda telah mengunduhnya dari suatu tempat yang cerdik dan Anda ingin menyelidikinya sebelum menjalankannya, atau Anda seorang sysadmin membantu beberapa pengguna dengan melihat di direktori home mereka, dll. Anda ingin membuat daftar direktori, jadi Anda mencoba mengetik ls, tetapi oops, Anda membuat kesalahan ketik, dan akhirnya mengetikkan sl. Penulis direktori jahat ini mengantisipasi ini dan meletakkan skrip shell di dalamnya yang disebut "sl" yang menjalankan 'rm -rf --no-preserve-root /' (atau sesuatu yang lebih berbahaya seperti memasang rootkit).
Muzer

2
Layak menjelaskan bahwa jika direktori saat ini di awal $ PATH, penyerang hanya bisa menimpa ls atau perintah umum lainnya
Délisson Junio

@Muzer Huuuge topi kertas timah di sini.
Sombrero Chicken

4
@GillBates Ini adalah hal yang perlu diwaspadai sebagai sysadmin yang harus berurusan dengan pengguna yang sebenarnya dan berpotensi jahat, atau seseorang yang menganalisis arsip yang mencurigakan untuk mencari nafkah. Jika tidak ada yang berlaku, maka saya setuju dengan Anda. Saya masih berpikir itu bukan kebiasaan yang baik untuk masuk, karena Anda tidak pernah tahu kapan keadaan Anda akan berubah, Anda mendapatkan salah satu dari pekerjaan ini, dan Anda akan terus-menerus mengutuk diri sendiri karena telah melatih diri untuk mengandalkan perilaku tidak aman; )
Muzer

10

Anda dapat memanggil penerjemah, misalnya

bash test

Dalam kasus ini, skrip akan berjalan walaupun tidak memiliki baris shebang (mis. #!/bin/bash) Atau bit yang dapat dieksekusi. Anda harus tahu penerjemah yang benar untuk menjalankannya juga. Anda dapat membaca baris shebang dari file terlebih dahulu untuk memastikan Anda memanggil juru bahasa yang benar, misalnya jika baris shebang mengatakan

#!/usr/bin/env python3

kamu akan menelepon

python3 test

7
interpreter hanya menafsirkan kode, mereka tidak akan menjalankan file biner
Mc Kernel

Jawaban ini agak logis karena mungkin interpreter dapat diberikan alias dalam file bashrc.

5
@McKernel poin bagus, itu hanya berfungsi jika ada juru bahasa, bukan untuk executable yang dikompilasi
Zanna

2
ada penerjemah untuk executable yang dikompilasi:/lib/ld.so
Dmitry Kudriavtsev

7

Sejauh yang saya tahu, tidak ada cara untuk mencapainya kecuali Anda memasukkan file di path env, jadi Anda bisa menjalankannya dengan mengetik saja: file

.filetidak akan berfungsi karena itu adalah nama file yang berbeda. Ini adalah file yang dipanggil .filedan tidak ./file.

Saya rasa slash mungkin sulit diketik untuk Anda karena tata letak non-Inggris, mungkin? Dalam hal ini, itu juga terjadi pada saya, jadi saya sering menukar tata letak keyboard saya ke bahasa Inggris dengan menekan Alt + Shift di Windows (saya menggunakan Linux dari ssh)


7

Orang-orang telah menyarankan .untuk menambahkan PATH, yang berbahaya karena itu menciptakan risiko bahwa Anda secara tidak sengaja akan menjalankan program jahat yang ditanam di direktori yang dapat ditulis oleh dunia. Tapi, jika Anda memiliki program dieksekusi dalam beberapa direktori yang Anda miliki dan ditulis hanya dengan Anda, maka itu aman (cukup aman?) Untuk menempatkan orang-orang sutradara (ies) ke dalam PATH, dengan menambahkan baris seperti

PATH=$PATH:~/dev/myprog1:~/dev/myprog2

ke ~/.bashrcfile Anda . Tentu saja ini berarti Anda dapat menjalankan program dari salah satu direktori tersebut dari mana saja di sistem file. Misalnya, Anda bisa cd /etcdan mengetik foo, dan itu akan berjalan ~/dev/myprog1/foo. Ini memiliki kelemahan kecil yaitu Anda tidak dapat memiliki program dengan nama yang sama di lebih dari satu direktori. Secara khusus, jika Anda memiliki program yang dipanggil foo keduanya ~/dev/myprog1dan ~/dev/myprog2, Anda tidak akan dapat menjalankan yang kedua kecuali dengan menentukan jalur. Demikian juga jika Anda memiliki ~/dev/myprog1/cat- tetapi mengapa Anda mau?


Pendekatan lain, jika Anda hanya memiliki beberapa program yang Anda lakukan dengan ini, adalah mendefinisikan alias untuk mereka:

alias gizmo='./gizmo'
alias gonzo='./gonzo'

Atau Anda dapat memanggil alias .gizmodan .gonzo jika Anda menemukan itu lebih intuitif.

Sebenarnya, ini memiliki, pada tingkat tertentu, risiko keamanan yang sama dengan menempatkan .Anda PATH. Jika pengguna jahat dapat membaca Anda .bashrcdan melihat alias Anda, maka ia mungkin menempatkan malware yang dipanggil gizmodan gonzodi direktori acak dengan harapan Anda akan menjalankannya. Lebih baik membuat ini menggunakan nama path absolut:

alias gizmo='~/dev/myprog1/gizmo'
alias gonzo='~/dev/myprog2/gonzo'

Omong-omong, Anda harus menghindari penamaan yang dapat dieksekusi test, karena itu adalah perintah shell builtin, dan Anda dapat menjalankan program dengan nama itu hanya dengan menentukan lintasan atau trik lain.


Atau Anda dapat membuat resep (jika Anda menggunakan Makefile) dan lakukan make gizmoatau make gonzo.
ihato

Maaf, tapi saya tidak yakin saya mengerti bagaimana itu terkait dengan pertanyaan atau jawaban saya. Apakah Anda menyarankan agar OP membuat Makefiledi setiap direktori, sehingga tindakan untuk make gizmomengakhiri dengan menjalankan gizmo ? (1) Itu tampak seperti cara canggung dalam melakukan hal yang sama dengan pfungsi, disarankan dalam pertanyaan, awalnya dilaksanakan oleh aitap , dan disempurnakan oleh Scott. (2) Bisakah Anda memberikan argumen seperti itu? ISTM yang make gizmo arg1 arg2setara dengan make gizmo; make arg1; make arg2.
G-Man Mengatakan 'Reinstate Monica'

1
(1) Mungkin asumsi saya salah tetapi tidak jelas bagi saya OP ingin menghindari menggunakan ./di setiap direktori . Dalam pikiran saya, dia sedang mengembangkan sesuatu dan hanya perlu menjalankan program yang dihasilkan ./filesering. Saya benar-benar tidak dapat memikirkan skenario lain di mana seseorang akan sering perlu menjalankan file lokal dan jika dia tidak menjalankannya sering dia tidak akan repot mengajukan pertanyaan (katanya sulit bukan tidak mungkin ) (2) tidak terlalu tetapi Anda bisa meneruskan argumen dalam resep.
ihato

(1) Ya, saya kira kita bisa sepakat bahwa motivasi OP dan ruang lingkup pertanyaannya tidak jelas. (2) Terima kasih atas tautannya.
G-Man Mengatakan 'Reinstate Monica'

3

Untuk memperluas jawaban Zanna tentang penerjemah (maaf, tidak ada perwakilan untuk komentar): "penerjemah" untuk executable asli (alias file ELF biner) adalah pemuat dinamis ( ld.so), tetapi biasanya tidak memahami sintaks yang Anda inginkan:

$ /usr/lib/ld-linux-x86-64.so.2 program
program: error while loading shared libraries: program: cannot open shared object file
$ /usr/lib/ld-linux-x86-64.so.2 ./program
<program is launched>

(juga, kecuali Anda terhubung ld.soke jalur Anda, Anda masih perlu menulis /s)


Ini khusus Linux, bukan? Bisakah Anda jelaskan lebih lanjut, mengapa ini berhasil? Saya pikir kernel (Linux) akan melakukan parsing dan memutuskan apakah dan bagaimana menjalankan biner, itu untuk apa binfmt_misc.
phk

2
@phk File ini khusus untuk Linux, tetapi konsep dynamic linker / loader tidak. Sebagai contoh, FreeBSD memiliki sendiri /libexec/ld-elf.so.1. Di Linux, ini tidak sesederhana "memutuskan cara menjalankan biner": binfmt_miscmendeteksi format file dengan angka ajaib (ELF, skrip shebang, CIL). Setelah itu, binfmt_elfpawang dipanggil. Ini mem-parsing header dan bagian ELF; .interpbagian berisi jalur pemuat dinamis; loader ini dimulai oleh kernel, melakukan relokasi, dan melompat ke _start. Pada FreeBSD (tidak yakin tentang yang lain) tidak ada binfmt, tetapi prinsipnya adalah +/- serupa.
bacondropped

1
@phk mengapa ini bekerja - ld.sotidak memiliki .interpdan terhubung secara statis, yang berarti tidak perlu untuk linker / loader dinamis lain untuk menyelesaikan simbol eksternal dan melakukan relokasi matematika.
bacondropped

ISTR Solaris juga memiliki sesuatu yang setara dengan ini.
G-Man Mengatakan 'Reinstate Monica'

3

Jika kita diizinkan untuk mengkonfigurasi hal-hal

mkdir -p ~/.local/bin
cat > ~/.local/bin/x << 'EOF'
#!/bin/sh
N="$1"
shift
exec "./$N" "$@"
EOF
chmod a+x ~/.local/bin/x

Kebanyakan distro modern menyertakan ~ / .local / bin dalam $ PATH (tambahkan export PATH="$HOME/.local/bin:$PATH"ke Anda ~/.profilejika milik Anda tidak). Maka Anda bisa menggunakan x fileuntuk menjalankan ./file.

Jangan mencoba mendefinisikan .perintah. Perintah . scriptsudah berjalan scriptdi shell saat ini. Ini memungkinkan scriptuntuk mendefinisikan variabel lingkungan untuk shell saat ini.


3
Saya pikir mungkin ada saran yang bagus di sini, tetapi tidak ada penjelasan tentang apa yang dilakukan semua ini. Saya bisa mengatasinya, tetapi pengguna yang tidak berpengalaman tidak akan memiliki kesempatan.
IMSoP

Tidak perlu menggeser $ 1. Adil exec "$@".
reinierpost

$ (ln -s /bin/ls my-ls && exec my-ls) # bash: exec: my-ls: not found
sourcejedi

(1) Tidak perlu shift $1; adil exec ./"$@". (2) Karena Anda berbicara tentang skrip shell, itu sedikit gunanya / menyesatkan untuk menyarankan orang untuk tidak mendefinisikan .perintah, karena tidak mungkin untuk membuat file bernama .. (Dimungkinkan, dan sangat tidak disarankan, untuk mendefinisikan alias atau fungsi shell yang disebut ..)
Scott

1

Jika kami diizinkan membuat skrip pembantu, Anda bisa membuat pembantu yang menambahkan pwd ke PATH, lalu jalankan

. pathhelper    #adds pwd to path
file            #now it can be run without ./

Ini menghindari menambahkan "." ke jalan dan mencemari profil. Anda dengan setiap jalur Anda mungkin pada suatu titik ingin menjalankan sesuatu.

Kita dapat mengambil pendekatan ini selangkah lebih maju dengan membuat helper yang meluncurkan shell baru dengan PATH yang dimodifikasi. Jika itu mengambil direktori sebagai parameter (menggunakan pwd sebagai default), itu akan berfungsi seperti pushdyang mengedit path. Anda mungkin harus sadar bahwa perubahan pada variabel lingkungan lain akan hilang saat keluar dari subkulit, tetapi dalam shell yang sudah berjalan lama, variabel PATH Anda tidak akan berantakan semua. Tergantung pada alur kerja Anda, ini mungkin menguntungkan.

:outer shell prompt$; subshellpathhelper    # launches a subshell with modified PATH
: subshell prompt $ ; file                  # in the subshell it can be run without ./

Tapi saya kira jika Anda ingin menjalankan dengan itu Anda bisa hack pushddan popdsehingga mereka dapat membuat modifikasi yang sama untuk jalan tanpa tanpa membuat subkulit yang akan kehilangan perubahan lain.

pushd --path ~/some/path/    # normal pushd plus adds target to path
file                         # it can be run without ./ until you popd

(Anda tidak dapat melakukan hal yang sama dengan cdkarena tidak memiliki analog popd.)

Anda juga bisa membuat pasangan pembantu yang berdedikasi untuk hanya menekan dan memunculkan entri PATH. Apa yang paling berhasil sangat tergantung pada pola penggunaan Anda.


Sebenarnya, Anda bisa melakukan sesuatu seperti itu cd, tetapi lebih jauh di luar sana: Buat file seperti .dircmds, dan retas cduntuk membuat perintah yang didefinisikan ./.dircmdstidak tersedia sebelum beralih dan tersedia segera setelah beralih.
ShadSterling

-1

Anda dapat menggunakan . script.shsintaks selama skrip yang ingin Anda jalankan ada di direktori saat ini.

Anda juga bisa mengawali dengan juru bahasa, seperti sh atau bash. contoh:bash script.sh


8
. script.shakan rusak jika skrip berisi exit, memiliki efek yang tidak diharapkan, misalnya jika skrip didefinisikan ulang "sementara"; itu juga hanya berfungsi untuk skrip untuk shell Anda saat ini
sourcejedi

@ sourcejedi Mengenai exitAnda bisa meletakkannya di dalam tanda kurung, yaitu subkulit, tetapi benar, itu masih akan hanya untuk skrip dalam shell yang sama.
phk

Pertanyaannya mengatakan "file yang dapat dieksekusi". Ini tidak akan berfungsi untuk biner yang dapat dieksekusi; hanya untuk skrip. Dan paragraf kedua Anda menduplikasi jawaban Zanna .
Scott

Yah, salahku, aku kebanyakan mengeksekusi dan dev bash stuff, jadi aku berasumsi kita berbicara tentang skrip bash :)
UltimateByte

Bukan hanya untuk skrip, tetapi hanya untuk skrip Bash.
Oskar Skog
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.