제목에서 대부분의 질문을 알 수 있듯이 .exe
끝에 명시적인 접미사를 지정하지 않고 어떻게 Windows 실행 파일을 실행할 수 있습니까?
explorer.exe .
예를 들어, explorer .
, 또는 , 또는 notepad.exe file
으로 및 기타 호출을 줄 입니다 .notepad file
docker.exe ps
docker ps
이를 수행하는 기본 방법이 있는지 또는 command not found
명령 이름에 사용 가능한 Linux 프로그램이 없는 경우 오류를 처리하고 실행 파일로 리디렉션하는 방법이 있는지 궁금합니다..exe
$Path
편집하다:
이전에 환경을 추가하는 것을 잊어버렸습니다. 여기 있습니다:
- 터미널: Windows 터미널
- Linux: WSL의 Ubuntu 20.04(Linux용 Windows 하위 시스템)
- 쉘: zsh
- 운영 체제: 윈도우 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
) 작동하지만 foo
. foo.exe
zsh에서는 작동하지 않지만 foo
cmd에서는 작동하고 이름이 지정된 프로그램을 호출하는 경우 foo.exe
다른 문제가 있는 것입니다.
답변2
세 가지 옵션이 있습니다.
항상 를 입력하세요
.exe
. 쉘에 명령 완성 기능이 있다고 가정하면 도움이 될 수 있습니다. 그러나 그것은 바로 당신이 피하고 싶은 것입니다.다른 사람들은 별칭 솔루션을 지적했습니다.
.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 쉘 파생물과 호환되도록 유닉스 버전 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에서 직접 사용되지 않는다는 것을 배웠습니다 .