如何在沒有明確指定 .exe 副檔名的情況下從終端執行 Windows 執行檔?
正如標題所說的大部分問題,我們如何在不指定
.exe
末尾顯式後綴的情況下執行 Windows 執行檔。例如減少呼叫 like
explorer.exe .
toexplorer .
, ornotepad.exe file
tonotepad file
, ordocker.exe ps
todocker ps
等。我想知道是否有本機方法可以這樣做,或者如果沒有帶有命令名稱的linux 程序可用,是否有辦法處理
command not found
錯誤並重定向到執行檔。.exe``$Path
編輯:
之前忘記添加環境了,這裡是:
- 終端:Windows終端
- Linux:WSL 上的 Ubuntu 20.04(Linux 的 Windows 子系統)
- 外殼:zsh
- 作業系統:Windows 10 1909
您可以設置一個
command_not_found_handler
. 未經測試:function command_not_found_handler { for ext in ${(s:;:)${PATHEXT-".com;.exe;.bat;.cmd;.vbs;.vbe;.js;.jse;.wsf;.wsh;.msc"}}; do if (( $+commands[$1$ext] )); then exec -- "$1$ext" "${@:2}" fi done print -ru2 "command not found: $1" return 127 }
請注意,這特別是 if
foo.exe
(或其他副檔名,例如.bat
)有效,但您希望能夠只鍵入foo
. 如果foo.exe
在 zsh 中不起作用但foo
在 cmd 中起作用並呼叫一個名為 的程序foo.exe
,那麼您將遇到不同的問題。
你有三個選擇。
- 始終鍵入
.exe
. 命令完成可能會有所幫助,假設你的 shell 有它。但這是你試圖避免的。- 其他人已經指出了別名解決方案。
- 在沒有 .exe 的情況下創建指向 Windows 執行檔的符號連結。這些應該放在路徑中的目錄中(在 Unix/Linux 文件系統上)。(您可能只想為這些添加一個目錄到您的路徑中。)我可能會這樣做:
cd ~/bin.windows_exes ln -s /path/to/windows/executables/*.exe . prename 's/.exe$//' *.exe
(
prename
是 的perl
版本rename
。這是rename
我知道和使用的。)然後通過以下方式添加到您的路徑:
PATH="$PATH":"$HOME"/bin.windows_exe
編輯:顯然OP想要一個安裝腳本。在這裡被拒絕之後(我同意,這有點簡單),OP將其作為他自己的答案發布並將支票移到那裡,所以我自己寫了。我試圖符合版本 7 unix,以便它與任何 Bourne shell 衍生產品兼容。
它包括設置輸出目錄、擴展列表、詳細或安靜、空執行和刪除連結的選項。小心不要覆蓋現有的東西,除非它會替換損壞的連結。
頂部的副檔名列表和預設輸出目錄可以編輯,底部的預設視窗目錄列表也可以編輯。(對於後者,我假設 MS-Windows 驅動器安裝在
/windows
.)您可以考慮將 MS-Windows 路徑中的任何目錄添加到此列表中。#!/bin/sh exts='exe bat cmd com vbs vbe js jse wsf wsh msc' output_directory="$HOME/.windows_binaries" quiet=false verbose=false dryrun=false remove=false debug=false usage() { echo "`basename "$0"`" '<options>' '[<windows_directories>]' echo ' -d dir Specify the output directory' echo ' -e ext Add a windows extension, like "exe"' echo ' -E Clear the list of extensions' echo ' -v, --verbose Verbose (report normal changes)' echo ' -q, --quiet Quiet (don'"'"'t report errors)' echo ' -n, --dryrun Do not make any changes' echo ' --remove Remove links that would otherwise be made' ( echo 'If no windows directories are specified,' echo 'everything in the PATH is done implicitly.' echo 'For Cygwin' echo 'or Microsoft'"'"'s "Windows Subsystem for Linux",' echo 'it is assumed' echo 'that PATH has been translated to Unix conventions.' ) | fmt exit 2 } add_link() { $debug && echo consider "$1" "$2" if test -h "$2" then # here, the target already exists, and is a link oldlink="`readlink "$2"`" if test "$1" = "$oldlink" then if $remove then $verbose && echo remove "$2" $dryrun || rm "$2" fi else if $remove then : else if test ! -e "$2" then # old link broken, replace it $dryrun || rm "$2" $dryrun || ln -s "$1" "$2" $verbose && echo replace broken "$2" as "$1" else $quiet || echo "$2" already links to "$oldlink" -- not changing it to "$1" fi fi fi elif $remove then : elif test -e "$2" then # here, the target already exists $quiet || echo Not replacing file "$2" else # here, the target does not exist $dryrun || ln -s "$1" "$2" $verbose && echo link "$2" as "$1" fi } add_directory() { dir="$1" case "$dir" in */) dir="` expr "$dir" : '\(*\)/' `" ;; esac $debug && echo consider "$1" for ext in $exts do for path in "$dir"/*."$ext" do # wildcards in bourne shell always return something, even if it is just the wildcard if test -f "$path" then fn=`basename "$path" ."$ext"` add_link "$path" "$output_directory"/"$fn" fi done done } ## Can't use getopt because it doesn't handle spaces, and windows directories ## are notorious for having spaces. Can't use getopts as it is too recent. have_dirs= mode= for arg in "$@" do case "$mode":"$arg" in :-d) mode=-d ;; :-d*) output_directory="`expr "$arg" : "-d\(*\)"`" ;; -d:*) output_directory="$arg" mode= ;; :-e) mode=-e ;; :-e*) exts="$exts `expr "$arg" : "-d\(*\)"`" ;; -e:*) exts="$exts $arg" mode= ;; :-E) exts="" ;; :-q) quiet=true ;; :--quiet) quiet=true ;; :-v) verbose=true ;; :--verbose) verbose=true ;; :-n) dryrun=true ;; :--dryrun) dryrun=true ;; :--remove) remove=true ;; :-*) echo Bad option "$arg" ; usage ;; :*) if test -d "$arg" then have_dirs=true else echo Argument "$arg" is not a directory usage fi ;; esac done if test -z "$exts" then echo No extensions specified '(and you cleared the list)' usage fi if test ! -d "$output_directory" then if $remove then echo Nothing to do exit 0 fi mkdir "$output_directory" $verbose && echo made directory "$output_directory" fi if test -n "$have_dirs" then mode= for arg in "$@" do case "$mode":"$arg" in :-[de]) mode=$arg ;; :-[de]*) ;; -[de]:*) mode= ;; :-[Eqvn]) ;; :--quiet) ;; :--verbose) ;; :--dryrun) ;; :--remove) ;; :*) add_directory "$arg" ;; esac done else # Do all the directories in the path. IFS0="$IFS" IFS=: for pdir in $PATH do IFS="$IFS0" add_directory "$pdir" done fi $remove && rmdir "$output_directory" 2>/dev/null $verbose && test ! -d "$output_directory" && echo remove directory "$output_directory"
編輯:修改腳本以使用 PATH 變數。OP 的問題暗示他已經獲得了他想在路徑中使用的所有 Windows 可執行目錄。