Ani*_*ahu 7 shell zsh windows oh-my-zsh windows-subsystem-for-linux
正如标题所说的大部分问题,我们如何在不指定.exe
末尾显式后缀的情况下运行 Windows 可执行文件。
例如减少像呼叫explorer.exe .
到explorer .
,或notepad.exe file
到notepad file
,或docker.exe ps
以docker ps
等
我想知道是否有本地方法可以这样做,或者是否有一种方法可以处理command not found
错误并重定向到.exe
可执行文件,如果$Path
命令名称中没有可用的 linux 程序。
编辑:
之前忘记加环境了,这里是:
你有三个选择。
始终键入.exe
. 命令完成可能会有所帮助,假设您的 shell 有它。但这是你试图避免的。
其他人已经指出的别名解决方案。
建立不带 .exe 的符号链接到 Windows 可执行文件。这些应该放在您路径中的一个目录中(在 Unix/Linux 文件系统上)。(您可能只想为这些在路径中添加一个目录。)我可能会这样做:
cd ~/bin.windows_exes
ln -s /path/to/windows/executables/*.exe .
prename 's/.exe$//' *.exe
Run Code Online (Sandbox Code Playgroud)
(prename
是 的perl
版本rename
。这是rename
我知道和使用的。)
然后添加到您的路径是通过:
PATH="$PATH":"$HOME"/bin.windows_exe
Run Code Online (Sandbox Code Playgroud)
编辑:显然 OP 想要一个安装脚本。在这里被拒绝后(我同意,这有点简单),OP 将其发布为他自己的答案并将支票移到那里,所以我写了自己的答案。我试图符合版本 7 unix,因此它可以与任何 Bourne shell 衍生产品兼容。
它包括设置输出目录、扩展列表、详细或安静、dryrun 和删除链接的选项。永远不要覆盖现有的东西,除非它会替换损坏的链接。
顶部的扩展列表和默认输出目录可以编辑,底部的默认窗口目录列表也可以编辑。(对于后者,我假设 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"
Run Code Online (Sandbox Code Playgroud)
编辑:修改脚本以使用 PATH 变量。OP 的问题隐含着他已经获得了他想要在路径中使用的所有 Windows 可执行目录。
您可以设置一个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
}
Run Code Online (Sandbox Code Playgroud)
请注意,如果foo.exe
(或其他扩展名,例如.bat
)有效,但您希望能够仅键入foo
. 如果foo.exe
在 zsh 中不起作用但foo
在 cmd 中工作并调用一个名为 的程序foo.exe
,则您会遇到不同的问题。
遵循@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
Run Code Online (Sandbox Code Playgroud)
然后我们可以将~/.windows_binaries
文件夹附加到路径中,这样如果没有找到 linux 可执行文件,将触发 windows 可执行文件:
在$HOME/.zshrc
文件中:
export PATH=$PATH:$HOME/.windows_binaries
Run Code Online (Sandbox Code Playgroud)
上述脚本的解释:
#!/usr/bin/zsh
- Shebang 将重定向要由 zsh 执行的脚本,因为我们确实使用了 bash 默认情况下不可用的过滤命令。mkdir -p $HOME/.windows_binaries
- 如果路径不存在,则创建它:)cd $HOME/.windows_binaries
- 将cwd更改为它for ext in $(...); do
- 循环遍历窗口中被视为脚本的每个扩展for command in ${(M)commands:#*$ext}; do
-$commands
索引当前 shell 中可以使用的所有命令,并使用 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
Run Code Online (Sandbox Code Playgroud)
我还了解到,正则表达式替换/字符串更改的 shell 替换比将其管道传输到诸如tr
. 而且IFS并不是直接在zsh中直接使用来扩展替换的,我们必须事先配置它。
归档时间: |
|
查看次数: |
2041 次 |
最近记录: |