Как запускать исполняемые файлы Windows из терминала без явного указания расширения.exe?

Ответ Иванивана(тюнингdhcpcd.con)хоть и правдоподобен, но в моем случае не сработал. Так что подозреваю, что дело не в DHCP. Я наткнулся на этот пост , в котором мне сказали, что проблема не в DHCP, а в NetworkManager. Добавление следующего к /etc/NetworkManager/NetworkManager.confрешило проблему для меня:

[main]
plugins=keyfile 
hostname-mode=none 

Подробнее об опции hostname-modeсм. man 5 NetworkManager.conf. Установка его на noneне позволяет NetworkManager устанавливать временное имя хоста, что и произошло в моем случае.

6
01.10.2020, 17:33
6 ответов

Следуя идее, предложенной @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, который будет перенаправлять скрипт для выполнения zsh, потому что мы использовали команду filter, которая по умолчанию недоступна в bash.
  • mkdir -p $HOME/.windows_binaries-Если пути не существует, то создайте его:)
  • cd $HOME/.windows_binaries-Измените cwd на него
  • for ext in $(...); do-Перебор всех расширений, рассматриваемых в Windows как скрипт
  • 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

Я также понял, что замена в оболочке регулярного выражения -replace/changes to string лучше, чем передача его какой-либо команде, например tr. И то, что IFS напрямую не используется для расширения подстановки непосредственно в zsh, мы должны настроить его заранее.

2
18.03.2021, 23:00

используйте встроенную функцию hash.

rehash() {
  hash -f
  local c
  for c in ${commands[(I)*.exe]}; hash ${c:r}=$commands[$c]
}
rehash

переопределение встроенной перефразировки -; что является сокращением для hash -f, поэтому, даже если для стиля rehashустановлено значение true, список перестраивается.

2
18.03.2021, 23:00

Создайте псевдоним в своем .zshrc.

alias docker='docker.exe' 

Затем, sourceэто, и вы готовы идти. Я бы подумал об этом только для исполняемых файлов, которые вам нужны. В конце концов, вы можете запустить Linux pingвместо ping.exe.

2
18.03.2021, 23:00

Вы можете просто создать кучу псевдонимов при запуске оболочки. Пожалуйста, учитывайте опасности, связанные с этим! Так что лично я бы не считал это идеальным решением.

Добавить к.zshrc

for command in $( IFS=':' ; find $PATH -executable -type f ) do
  if [[ $(basename $command.exe) != $(basename $command) ]] ; then
    alias $(basename $command.exe)=$command
  fi
done

(Честно говоря, я не уверен, следует ли вам заменить, например,. findпо find.exe, здесь.)

ОПАСНОСТИ

  1. Конфликтующие псевдонимы, которые вы установили ранее. Лучше всего выполнить до того, как эти псевдонимы будут установлены. Типичными примерами могут быть, например. alias rm='rm -i'. Также обратите внимание на то, относятся ли эти стандартные меры безопасности к rm.exeили rm!

  2. $PATHчитается спереди назад и выполняется первая совпадающая команда. Например. если у вас есть локальный ~/.my_executables/в вашем $PATHи вы используете идентичное имя команды для переопределения стандартной команды, приведенное выше изменит это. В этом случае, например. передайте результатыfind-через tacдля поддержания надлежащего порядка.

  3. Вероятно, больше мне сейчас не приходит в голову.

1
18.03.2021, 23:00

Вы можете настроить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), работает, но вы хотите иметь возможность набирать только foo. Если foo.exeне работает в zsh, но fooработает в cmd и вызывает программу с именем foo.exe, у вас другая проблема.

5
18.03.2021, 23:00

У вас есть три варианта.

  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 опубликовал его как свой собственный ответ и переместил туда чек, поэтому я написал свой собственный. Я попытался соответствовать версии 7 unix, чтобы она была совместима с любой производной оболочки Bourne.

Он включает в себя параметры для установки выходного каталога, списка расширений, подробного или тихого отображения, пробного запуска и удаления ссылок. Никогда не перезаписывайте существующие вещи, за исключением того, что это заменит неработающую ссылку.

Список расширений и выходной каталог по умолчанию вверху можно редактировать, как и список каталогов 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. В вопросе ОП подразумевается, что у него уже есть все исполняемые каталоги Windows, которые он хочет использовать в пути.

5
18.03.2021, 23:00

Теги

Похожие вопросы