1 (изменено: Rumata, 2022-11-05 13:57:20)

Тема: CMD/BAT: BusyBox запускалка, BusyBox Runner

Доработал обертку-запускалку для BusyBox, компактного набора консольных утилит Юникс.

Требования

Для работы необходимо:

-- Загрузить скрипт bb.bat из репозитория https://github.com/ildar-shaimordanov/m … md/busybox.
-- Загрузить сам BusyBox со страницы https://frippery.org/busybox/ (любая, 64- или 32-битная, по вашему желанию).
-- Поместить оба файла в каталог, видимый из переменной окружения $PATH.

или...

-- Загрузить скрипт bb.bat из репозитория https://github.com/ildar-shaimordanov/m … md/busybox.
-- Поместить файл в каталог, видимый из переменной окружения $PATH.
-- Чтобы загрузить последнюю версию 32-битной или 64-битной сборки BusyBox, выполнить одну из команд, соответственно:

bb --download win32

или

bb --download win64

Загруженный файл сохранется в одном каталоге со скриптом. Для загрузки требуется PowerShell.

Применение

1. Запуск встроенных функций BusyBox

Запустить функцию и передать, если необходимо, опции:

bb function [function-options]

Фактически, это тоже самое, что делает BusyBox:

busybox function [function-options]

2. Запуск команды или скрипта из переменной $PATH

Выполнить внешнюю команду или скрипт, найденные в переменной $PATH или казанные по абсолютному или относительному пути:

bb [shell-options] [DIR]command [command-options]
busybox [sh [shell-options]] [DIR]command [command-options]

3. Запуск однострочного скрипта

bb [shell-options] -c "script"
busybox sh [shell-options] -c "script"
Исходный код

Актуальные на момент написания этого текста версии скриптов.

bb.bat


: ; [ $# -gt 0 ] || exec sed -n "s/^:: \?//p" << '::::'
:: Simplify running scripts and commands with BusyBox
::
:: USAGE
::   Print BusyBox help pages
::     bb --help
::     bb --version
::     bb --list[-full]
::
::   Run a built-in BusyBox function
::     bb function [function-options]
::
::   Run an executable from $PATH or specified with DIR
::     bb [shell-options] [DIR]command [command-options]
::
::   Run a one-liner script
::     bb [shell-options] -c "script"
::
::   Download the latest 32-bit or 64-bit build of BusyBox
::     bb --download win32
::     bb --download win64
::
:: SEE ALSO
::   Learn more about BusyBox following these links:
::
::   https://busybox.net/
::   https://frippery.org/busybox/
::   https://github.com/rmyorston/busybox-w32
::::
: << '____CMD____'
@echo off

setlocal

set "BB_EXE="

:: First: look for the latest instance next to this script
if not defined BB_EXE for /f "tokens=*" %%f in ( '
	dir /b /o-n "%~dp0busybox*.exe" 2^>nul
' ) do if not defined BB_EXE if exist "%~dp0%%~f" set "BB_EXE=%~dp0%%~f"

:: Second: look for the instance in $PATH
for %%f in (
	busybox.exe
	busybox64.exe
) do if not defined BB_EXE if not "%%~$PATH:f" == "" set "BB_EXE=%%~$PATH:f"

:: Fail, if BusyBox not found and download not required
if not defined BB_EXE if /i not "%~1" == "--download" (
	2>nul echo:ERROR: BusyBox executable not found
	exit /b 1
)

:: ========================================================================

:: Try to download
if /i "%~1" == "--download" (
	for %%p in ( "powershell.exe" ) do if "%%~$PATH:p" == "" (
		>&2 echo:%%p is required
		goto :EOF
	)

	set "BB_URL="
	set "BB_DST="

	if /i "%~2" == "win32" (
		set "BB_URL=https://frippery.org/files/busybox/busybox.exe"
		set "BB_DST=%~dp0busybox.exe"
	) else if /i "%~2" == "win64" (
		set "BB_URL=https://frippery.org/files/busybox/busybox64.exe"
		set "BB_DST=%~dp0busybox64.exe"
	) else (
		>&2 echo:win32 or win64 required
		goto :EOF
	)

	echo:Downloading started...
	set BB_URL
	set BB_DST

	powershell -NoLogo -NoProfile -Command "[Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12;$w=New-Object System.Net.WebClient;$w.DownloadFile($Env:BB_URL,$Env:BB_DST)"

	echo:Downloading completed

	goto :EOF
)

:: ========================================================================

:: Locate the history file in the $TEMP directory
set "HISTFILE=%TEMP%\.ash_history"

:: Locate the history file next to Busybox executable
::set "HISTFILE=%~dp0.ash_history"

:: Another way to locate the history file is to set HOME dir
::for %%p in ( "%~dp0." ) do set "HOME=%%~fp"

:: ========================================================================

if defined BB_DEBUG (
	@prompt +$S
	@echo on
)

"%BB_EXE%" sh "%~f0" %*
exit /b %ERRORLEVEL%

:: ========================================================================

____CMD____

case "$1" in
'' )
	# It's never reachable part - learn why at the top of the script
	exit
	;;
--help | --list | --list-full )
	busybox $1
	exit
	;;
--version )
	busybox --help | head -2
	exit
	;;
esac

# Add the BusyBox location to the $PATH
[[ ";$PATH;" =~ ";$( dirname "$0" );" ]] \
|| PATH="$( dirname "$0" );$PATH"

[ -z "$BB_DEBUG" ] || set -x

case "$1" in
-* | +* )
	sh "$@"
	;;
* )
	eval 'exec "$@"'
	;;
esac

# =========================================================================

# EOF

clp

Скрипт для работы с буфером обмена в обе стороны (копировать в буфер, копировать из буфера)

https://github.com/ildar-shaimordanov/m … /clipboard


#!/bin/sh

# =========================================================================

CLIP_GET=''
CLIP_PUT=''
CLIP_DEV=''
CLIP_IMP=''

CLIP_EOL=''
DOS2UNIX=''
UNIX2DOS=''

CLIP_ENC=''
ICONV=''

VERBOSELY=''

# =========================================================================

print_usage() {
	echo "\
Copy data from and/or to the clipboard

Usage:
	clp [OPTIONS]
	clp [OPTIONS] | ...
	... | clp [OPTIONS]

Formatting options
	-u	dos2unix
	-d	unix2dos

Encoding options
	-f encoding
	-t encoding
		Encodings for input and output, respectively
	-c	Discard silently unconvertible characters

Information options
	-h	Display this help message
	-v	Display the executable command
	-V	Display versions of tools
"
}

# shellcheck disable=SC3028
print_version() {
	exec 2>/dev/null
	uname -s || cmd /c ver || echo "${OSTYPE:-${OS:-unknown}}"
	printf 'imp=%s eol=%s enc=%s\n' \
		"${CLIP_DEV:-${CLIP_IMP:-${CLIP_GET%% *},${CLIP_PUT%% *}}}" \
		"${DOS2UNIX%% *},${UNIX2DOS%% *}" \
		"${ICONV%% *}"
}

# =========================================================================

die() {
	warn "$*"
	exit 1
}

warn() {
	echo "$*">&2
}

not_supported() {
	warn "$1 not supported"
}

# =========================================================================

# shellcheck disable=SC2016
getclip() {
	posh \
	'Get-Clipboard -Raw | Write-Host -NoNewLine'
}

# shellcheck disable=SC2016
putclip() {
	posh \
	'$b = @(); $i = [Console]::OpenStandardInput();' \
	'do { $b += @{ c = 0; d = [byte[]]::new(1048576) } }' \
	'while ( $b[-1].c = $i.Read($b[-1].d, 0, $b[-1].d.count) )' \
	'$a = $b | ForEach-Object { $_.d[0..($_.c - 1)] };' \
	'[System.Text.Encoding]::UTF8.GetString($a) | Set-Clipboard'
}

posh() {
	powershell -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "$*"
}

# =========================================================================

# shellcheck disable=SC3028
case "$OSTYPE" in
darwin*	) CLIP_OS=darwin ;;
*	) CLIP_OS='' ;;
esac

if command -v xsel >/dev/null
then
	# Unixes: first attempt - preferable way
	CLIP_GET='xsel --clipboard --output'
	CLIP_PUT='xsel --clipboard --input'
elif command -v xclip >/dev/null
then
	# Unixes: second attempt - another way
	CLIP_GET='xclip -selection clipboard -out'
	CLIP_PUT='xclip -selection clipboard -in'
elif [ "$CLIP_OS" = "darwin" ]
then
	# OSX? It has its own way
	command -v pbpaste >/dev/null && CLIP_GET='pbpaste'
	command -v pbcopy  >/dev/null && CLIP_PUT='pbcopy'
elif [ -c /dev/clipboard ]
then
	# Cygwin?
	CLIP_DEV='/dev/clipboard'
	CLIP_GET="cat - < $CLIP_DEV"
	CLIP_PUT="cat - > $CLIP_DEV"
elif [ "$OS" = "Windows_NT" ] && command -v powershell >/dev/null
then
	# BusyBox, UnxUtils or something else similar?
	CLIP_IMP='powershell'
	CLIP_GET='getclip'
	CLIP_PUT='putclip'
fi

# =========================================================================

if command -v dos2unix >/dev/null
then
	DOS2UNIX=dos2unix
elif command -v sed >/dev/null
then
	DOS2UNIX='sed "s/\r$//"'
elif command -v awk >/dev/null
then
	DOS2UNIX='awk -v RS="\r?\n" -v ORS="\n" 1'
elif command -v gawk >/dev/null
then
	DOS2UNIX='gawk -v RS="\r?\n" -v ORS="\n" 1'
fi

if command -v unix2dos >/dev/null
then
	UNIX2DOS=unix2dos
elif command -v sed >/dev/null
then
	UNIX2DOS='sed "s/[^\r]$/&\r/"'
elif command -v awk >/dev/null
then
	UNIX2DOS='awk -v RS="\r?\n" -v ORS="\r\n" 1'
elif command -v gawk >/dev/null
then
	UNIX2DOS='gawk -v RS="\r?\n" -v ORS="\r\n" 1'
fi

# =========================================================================

if command -v iconv >/dev/null
then
	ICONV='iconv'
fi

# =========================================================================

while getopts ":hVvudf:t:c" arg
do
	case "$arg" in
	h ) print_usage ; exit ;;
	V ) print_version ; exit ;;
	v ) VERBOSELY=1 ;;

	u ) CLIP_EOL="$DOS2UNIX" ; [ -n "$CLIP_EOL" ] || not_supported dos2unix ;;
	d ) CLIP_EOL="$UNIX2DOS" ; [ -n "$CLIP_EOL" ] || not_supported unix2dos ;;

	f | t | c )
		CLIP_ENC="$ICONV"
		CLIP_ENC_OPTS="$CLIP_ENC_OPTS -$arg$OPTARG"
		[ -n "$CLIP_ENC" ] || not_supported iconv
		;;

	: ) die "Argument expected for -$OPTARG" ;;
	* ) die "Illegal option: -$OPTARG" ;;
	esac
done

if [ -t 0 ]
then
	# clp
	# clp | ...
	[ -n "$CLIP_GET" ] || die "No tool to paste from clipboard"
	CLIP_RUN="$CLIP_GET"
	CLIP_RUN="$CLIP_RUN${CLIP_EOL:+ | $CLIP_EOL}"
	CLIP_RUN="$CLIP_RUN${CLIP_ENC:+ | $CLIP_ENC$CLIP_ENC_OPTS}"
elif [ -t 1 ]
then
	# ... | clp
	[ -n "$CLIP_PUT" ] || die "No tool to copy to clipboard"
	CLIP_RUN="$CLIP_PUT"
	CLIP_RUN="${CLIP_EOL:+$CLIP_EOL | }$CLIP_RUN"
	CLIP_RUN="${CLIP_ENC:+$CLIP_ENC$CLIP_ENC_OPTS | }$CLIP_RUN"
fi

# ... | clp | ...
[ -n "$CLIP_RUN" ] || die "Useless use in the middle of the pipe"

[ -n "$VERBOSELY" ] && set -x
eval "$CLIP_RUN"

# =========================================================================

# EOF
( 2 * b ) || ! ( 2 * b )

2 (изменено: Rumata, 2021-04-12 11:14:27)

Re: CMD/BAT: BusyBox запускалка, BusyBox Runner

Немного "косметических" изменений:
-- чуть расширил страницу справки скрипта
-- расширил обработку основных опций BusyBox: --help, --list, --list-full
-- удалил javascript код
-- полная справка выводится только средствами самого BusyBox и только при его наличии
-- улучшил поиск самого BusyBox

( 2 * b ) || ! ( 2 * b )

3 (изменено: Rumata, 2021-04-12 11:14:47)

Re: CMD/BAT: BusyBox запускалка, BusyBox Runner

-- добавил опции --download win32 и --download win64
-- улучшил и систематизировал способы вызова внутренних функций, внешних команд и однострочных сборных команд

Последняя на данный момента версия -- в первом сообщении. Все актуальные изменения -- по ссылке.

( 2 * b ) || ! ( 2 * b )

4

Re: CMD/BAT: BusyBox запускалка, BusyBox Runner

-- добавил поддержку переменной BB_DEBUG для отображения процесса запуска
-- косметические изменения
-- начальный пост отредактирован обновлением исходного кода

( 2 * b ) || ! ( 2 * b )

5 (изменено: Rumata, 2021-05-22 09:49:19)

Re: CMD/BAT: BusyBox запускалка, BusyBox Runner

- перенес обработку параметров командной строки в shell (за исключением --download)
- добавил clp, внешний скрипт для работы с буфером обмена с обе стороны (копировать в буфер и из буфера)
- добавлена проверка переменной окружения $PATH, при необходимости добавляется путь до BusyBox

Все изменения -- в первом сообщении.

( 2 * b ) || ! ( 2 * b )

6

Re: CMD/BAT: BusyBox запускалка, BusyBox Runner

Улучшил скрипт для работы с буфером обмена
-- копирование из буфера работает правильно
-- поддерживаются опции опции для манипуляций с переводами строк

-u - в юникс-стиле (LF)
-d - в дос-стиле (CRLF)

Все изменения -- в первом сообщении.

( 2 * b ) || ! ( 2 * b )

7

Re: CMD/BAT: BusyBox запускалка, BusyBox Runner

Rumata, а чем не устраивает такой вариант:

busybox --install C:\path\to\directory

Omitting the directory will result in the links being made in the same directory
as the busybox.exe executable you're running. The --install option creates 'hard'
links which are available on NTFS filesystems but not FAT.
Adding the option -s creates symbolic links, but this may not work if you don't
have the required privileges.

PS За clp огромное спасибо.

Нас невозможно сбить с пути, нам пофигу куда идти.

8 (изменено: Rumata, 2021-08-30 15:52:12)

Re: CMD/BAT: BusyBox запускалка, BusyBox Runner

DnsIs пишет:

чем не устраивает такой вариант

Лишние сущности. Хардлинки - хорошо, но плохо распознаются при копировании (бекап). Софтлинки в busybox не работают (по крайней мере, у меня на Win10).

DnsIs пишет:

За clp огромное спасибо

Пожалуйста. Аналогичная функция под Cygwin чуточку проще - там не используются Powershell и команда clip, а чтение/запись осуществляется через псевдоустройство /dev/clipboard.

( 2 * b ) || ! ( 2 * b )