Zsh

如何在沒有明確指定 .exe 副檔名的情況下從終端執行 Windows 執行檔?

  • May 12, 2022

正如標題所說的大部分問題,我們如何在不指定.exe末尾顯式後綴的情況下執行 Windows 執行檔。

在此處輸入圖像描述

例如減少呼叫 like explorer.exe .to explorer ., or notepad.exe fileto notepad file, or docker.exe pstodocker 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,那麼您將遇到不同的問題。

你有三個選擇。

  1. 始終鍵入.exe. 命令完成可能會有所幫助,假設你的 shell 有它。但這是你試圖避免的。
  2. 其他人已經指出了別名解決方案。
  3. 在沒有 .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 可執行目錄。

引用自:https://unix.stackexchange.com/questions/612352