.exe拡張子を明示的に指定せずに端末でWindows実行可能ファイルを実行するにはどうすればよいですか?

.exe拡張子を明示的に指定せずに端末でWindows実行可能ファイルを実行するにはどうすればよいですか?

タイトルからほとんどの質問がわかるように、最後に明示的なサフィックスを指定せずに.exeWindowsの実行可能ファイルをどのように実行できますか?

ここに画像の説明を入力してください。

explorer.exe .たとえば、、、、、explorer .またはnotepad.exe fileで、および他の呼び出しを減らします。notepad filedocker.exe psdocker ps

これを行う基本的な方法があるか、command not foundコマンド名に利用可能なLinuxプログラムがない場合は、エラーを処理して実行可能ファイルにリダイレクトする方法があるかどうか疑問に思います。.exe$Path

編集する:

以前は環境を追加するのを忘れていました。ここにあります:

  • ターミナル:Windowsターミナル
  • Linux:WSLのUbuntu 20.04(Linux用Windowsサブシステム)
  • シェル:zsh
  • オペレーティングシステム:Windows 10 1909

答え1

設定できます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
}

これはfoo.exe(または他の拡張機能など.bat)機能しますがfoofoo.exezshでは機能しませんが、foocmdでは機能し、名前付きプログラムを呼び出す場合は、foo.exe他の問題があります。

答え2

3つのオプションがあります。

  1. 常に入力してください.exe。シェルにコマンド補完機能があると仮定すると、役に立ちます。しかし、それはあなたが避けたいものです。

  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が自分の答えで投稿し、小切手をそこに移したので、直接作成しました。私はBourneシェル派生と互換性があるようにUnixバージョン7に従おうとしました。

これには、出力ディレクトリの設定、リストの拡張、冗長または自動実行、リンクの削除などのオプションが含まれます。壊れたリンクを置き換えない限り、既存のコンテンツを上書きしないように注意してください。

上部の拡張ディレクトリとデフォルト出力ディレクトリのリストは、下部に接続されているデフォルトのWindowsディレクトリのリストと同様に編集できます。 (後者の場合は、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実行可能ディレクトリを取得したことです。

答え3

にエイリアスを作成します.zshrc

alias docker='docker.exe' 

その後sourceは行ってもいいです。必要な実行可能ファイルに対してのみこれを実行することをお勧めします。結局のところ、あなたはおそらく.NETのping代わりにLinuxを実行したいと思いますping.exe

答え4

@DavidGが提供したアイデアに従います。私が作りました。誰かが幸せになることを願っています:)

次のスクリプトは、Windows上のすべての実行可能ファイルが存在しない場合、欠落しているディレクトリとシンボリックリンクを生成します。

#!/usr/bin/zsh

mkdir -p $HOME/.windows_binaries
cd $HOME/.windows_binaries

for ext in $( echo ${PATHEXT-".com;.exe;.bat;.cmd;.vbs;.vbe;.js;.jse;.wsf;.wsh;.msc"} | tr \; ' ' ); do
  for command in ${(M)commands:#*$ext}; do
    if [ -f $(basename $command $ext) ]; then; else
      ln -s $command $(basename $command $ext)
    fi
  done
done

~/.windows_binariesその後、Linux実行可能ファイルが見つからない場合は、Windows実行可能ファイルがトリガーされるようにフォルダをパスに追加できます。

$HOME/.zshrcファイルから:

export PATH=$PATH:$HOME/.windows_binaries

上記のスクリプトの説明:

  • #!/usr/bin/zsh- Shebangはbashでデフォルトで使用できないフィルタリングコマンドを使用するため、zshで実行するようにスクリプトをリダイレクトします。
  • mkdir -p $HOME/.windows_binaries- パスが存在しない場合は生成してください:)
  • cd $HOME/.windows_binaries- cwdをそれに変更
  • for ext in $(...); do- スクリプトと見なされるウィンドウの各拡張を繰り返します。
  • for command in ${(M)commands:#*$ext}; do$commands– 現在のシェルで使用可能なすべてのコマンドをインデックス化し、zsh フィルタを使用して拡張子$extで終わるコマンドをフィルタリングします。
  • if [ -f $(basename $command $ext) ]; then; else- 拡張子のないコマンドへのシンボリックリンクが作成されている場合はスキップし、そうでない場合はを使用して生成を続けますln -s

編集する:

スクリプトの最適化に役立つ @user414777 ありがとうございます。今は約2-3倍速くなりました(7-9秒)。

#!/usr/bin/zsh

mkdir -p $HOME/.windows_binaries
cd $HOME/.windows_binaries

all_exts=${${${PATHEXT-".com;.exe;.bat;.cmd;.vbs;.vbe;.js;.jse;.wsf;.wsh;.msc"}//;/|}//./}
IFS=$'\n'

if [ $ZSH_VERSION ]; then setopt sh_word_split; fi

for command in $(whence -psm "*.($all_exts)"); do
  sym_name=${${command##*/}%.*}
  if [ -f $sym_name ]; then; else
    ln -s $command $sym_name
  fi
done

trまた、正規表現の置換/文字列の変更シェルの交換は、たとえばパイプで接続するよりも優れており、交換を拡張するためにIFSがzshで直接使用されないことを学びました。

関連情報