POSIX 및 Windows에서 실행되는 실행 가능한 스크립트 파일


16

도전 과제 : 임의의 Windows 관련 코드를 실행하기 위해 foo.cmd바닐라 Windows cmd.exe프롬프트 (PowerShell이 ​​아닌 관리자 모드가 아님)에서 호출 할 수 있는 단일 스크립트 파일 을 작성하십시오 ...

> .\foo.cmd
Hello Windows! 

... 또한 쉘 전형적인 POSIX 호환 (리눅스 / OSX)에서 변경되지 않은 호출 할 프롬프트 ( bash, tcsh또는 zsh), 임의의 POSIX 특정 코드를 실행합니다 :

$ chmod a+x foo.cmd
$ ./foo.cmd
Hello POSIX!

... 타사 통역사 / 도구를 설치하거나 만들 필요가 없습니다.

나는 이것이 가능하다는 것을 알고 있지만 부스러기로 (즉, Windows에서는 하나 또는 두 줄의 쓰레기 / 오류 메시지가 "Hello Windows!"전에 stderr 또는 stdout으로 인쇄됩니다).

이기는 기준은 (첫 번째) 크래프트 라인 수와 (두 번째) 크래프트 문자 수를 최소화하는 것입니다.

크루프 트는 (임의의) 페이로드 코드에 의해 생성되지 않은 콘솔 출력 (stdout 또는 stderr)으로 정의 될 수 있습니다. 빈 줄은 줄 수로 계산됩니다. 줄 바꿈은 문자 수에 포함되지 않습니다. Cruft 점수는 두 플랫폼에서 합산되어야합니다. 이와 같은 메커니즘을 무시 cls하고 부스러기를 제거하지만 이전 터미널 출력을 비워야합니다. @echo off아직 설정 하지 않았기 때문에 Windows가 명령을 에코하는 경우 현재 디렉토리 및 프롬프트를 인쇄하는 데 사용하는 문자를 제외하십시오.

두 번째 기준은 내부 솔루션의 단순성 / 우아함입니다 foo.cmd. "인프라"가 임의의 페이로드 코드에 직접 관련되지 않은 문자로 정의 된 경우 먼저 인프라 문자가 포함 된 행 수를 최소화하고 두 번째로 총 인프라 수 문자.

CRLF 줄 끝이있는 파일에도 불구하고 POSIX 부분이 작동하면 추가로 도움이됩니다! (마지막 부분이 가능한지 확실하지 않습니다.)

다른 사람들이 기회를 얻은 후에 여기에 게시 할 기존 솔루션은 6 줄의 인프라 코드 (줄 바꿈을 제외한 52 자)를 사용합니다. 5 줄의 cruft를 생성하며, 그중 2 줄은 Windows에서 발생합니다 (줄 바꿈을 제외하고 그 줄 중 2 줄에 나타나는 현재 디렉토리 / 프롬프트 문자열을 제외하고 30 자).


나중에 쉘 / 배치 스크립트로?
고양이

1
누구나 DOS를위한 온라인 시도 환경을 알고 있습니까?
디지털 외상

1
문자를 찾았 지만 ":", "\", "{"또는 "}"문자를 입력 할 수 없습니다. :-/
Digital Trauma

@DigitalTrauma 와인이있다 (만약 당신이 그것을 설치하지 않았 으면, 그것이 편리하기 때문에 설치해야한다)
고양이

1
@ cat thanks-내 대답은 와인에서 작동하는 것 같습니다.
디지털 외상

답변:


15

부스러기 라인 0 개, 부스러기 문자 0 개, 인프라 2 개 라인 21 개 문자, CRLF ok

:<<@goto:eof
@echo Hello Windows!
@goto:eof
echo "Hello POSIX!" #

다른 솔루션을 제거했습니다.

exit /bDigital Trauma의 답변을 사용한 17 자 :

:<<@exit/b
@echo Hello Windows!
@exit/b
echo "Hello POSIX!" #

강력한 도전자! 특히 두 번째 버전 (단순성 / 우아함 기준에서 첫 번째 버전과 같은 방식으로 페이로드 라인을 혼동하지 않는 것이 훨씬 좋습니다). 이것은 Windows 및 OSX에서 나를 위해 실행됩니다. 처음에는 : command not found빈 줄이 posix 페이로드에 들어갈 때마다 한 줄의 cruft를 얻었 지만 마침내 :첫 번째 줄이 아니라 CRLF로 보호되지 않은 것으로 나타났습니다 #. #!필자는 이전 버전의 Windows cruft 라인 중 두 라인을 담당 하는 라인이 필요하지 않다는 소식을 들었다.
jez

첫 번째 버전은 점수 매기기가 어렵습니다 . 페이로드의 모든 줄에 문자 : ` >&3` \ 를 추가 할 수 있기 때문에 인프라 비용이 임의로 높다고 말할 수 있습니다.
jez

@jez 당신은 답변 점수 점수를 계산하고 있습니까? 그렇다면 질문을하는 방법을 훨씬 명확하게해야합니다.
디지털 외상

저는 codegolf를 처음 사용하기 때문에 TBH는 어떻게 든 객관적으로 답변의 점수를 매길 것으로 생각했습니다 . 그럼에도 불구하고 나는 그 질문이 분명하다고 생각한다. 첫째, 쇄석 선의 수; 쪼그리고 앉는 캐릭터 수만큼 그와의 관계를 끊으십시오. 그런 다음 인프라 라인 수, 인프라 문자 수 지미의 첫 번째 솔루션과 같이 페이로드 라인을 뒤섞는 솔루션을 기대하지 않았습니다. 나는 그게 바람직하지입니다 명확하게 약간 질문을 변경할 수 있습니다 (죄송합니다 나는 그의 두 번째 솔루션이나 지금까지 당신의 모든 버전에 영향을 생각하지 않는 약간의 골대 변화뿐만)
제즈

우리의 답변이 수렴되는 것처럼 보입니다. ;-) heredoc 사용법으로 점수를 얻는 데 우위가 있습니다. 마지막이 #필요한가요?
디지털 외상

4

0 cruft + 4 개의 인프라 라인 + 32 개의 인프라 문자 LF & CRLF OK.

이것은 Amiga 비트와 다른 불필요한 라인이 제거 된 이 블로그 에서 찾은 것을 기반으로합니다 . DOS 줄을 주석 대신 따옴표로 숨겼습니다.\줄 계속 CRLF와 LF 모두에서 작동 할 수 있습니다.

@REM ()(:) #
@REM "
@ECHO Hello Windows!
@EXIT /B
@REM "
echo Hello POSIX!

DOS CRLF 또는 * nix LF 라인 엔딩을 사용하면 Ubuntu, OSX 및 와인에서 작동합니다.

ubuntu@ubuntu:~$ ./dosix.bat
Hello POSIX!
ubuntu@ubuntu:~$ wine cmd.exe
Wine CMD Version 5.1.2600 (1.6.2)

Z:\home\ubuntu>dosix.bat
Hello Windows!

Z:\home\ubuntu>exit
ubuntu@ubuntu:~$ 

* nix 머신 (OSX 포함)에서 이것을 정확하게 (CRLF로) 작성하려면 다음을 터미널에 붙여 넣으십시오.

[ $(uname) = Darwin ] && decode=-D || decode=-d
ubuntu@ubuntu:~$ base64 $decode > dosix.bat << EOF
QFJFTSAoKSg6KSAjDQpAUkVNICINCkBFQ0hPIEhlbGxvIFdpbmRvd3MhDQpARVhJVCAvQg0KQFJF
TSAiDQplY2hvIEhlbGxvIFBPU0lYIQ0K
EOF

좋아 보인다! dosix좋은 이름입니다. 그러나 내 Mac (OS 10.9.4, Darwin Kernel 버전 13.3.0, GNU bash 버전 3.2.51)에서는 다음과 같이 실행되지 않습니다 ./dosix.cmd: line 13: syntax error: unexpected end of file .
jez

@jez는 UTF-8로 인코딩 된 파일을 저장하고 Windows 줄 끝을 유지해야합니다!
cat

아, 그것은 무의식적으로 Windows 줄 끝이 있었고 첫 번째 버전을 사용했기 때문에 발생했습니다.
jez December

삽입 (또는 Cv)을 사용하여 Bash에 CR 문자를 입력하고 입력 (또는 Cm) 할 수 있습니다.
jimmy23013

@jez 따라서 이것은 cruft 라인 + 4 인프라 라인 + 32 인프라 chars로 평가됩니다. 이 숫자들을 의미있는 방식으로 결합하여 단일 점수를 비교해야합니까?
디지털 외상

2

이미 사용 된 솔루션은 이미 구타되었으므로 게시 할 것입니다. Digital Trauma 와 동일한 블로그 항목을 읽었어야한다고 생각하는 동료가 제공 한 것입니다 .

#!/bin/sh # >NUL 2>&1
echo \
@goto c \
>/dev/null
echo "Hello Posix!"
exit
:c
@echo Hello Windows!
  • Windows cruft : 5 줄 (두 줄은 비어 있음) / 30 자
  • OSX cruft : 0
  • 인프라 : 6 줄 / 52 문자
  • CRLF 호환성 : #!회선에 이름이 지정된 통역사 가 신경 쓰지 않는 경우에만 (따라서 sh친구 와 같은 표준 통역사는 실패합니다)

POSIX에서 스크립트는 항상로 시작 #!합니다. 이는 POSIX 시스템에서 유효한 스크립트가 될 수있는 유일한 방법입니다. 다른 스크립트 중 일부는 다음과 같은 경우에 실행될 수 있지만 결함이있는 스크립트에 대한 해결 방법이있는 쉘에서 시작된 경우에만 가능합니다.
kasperd

알아 둘만 한! POSIX 준수에 대한 엄격한 기준에 대해 애매한 것 같습니다. 제 진짜 목표는 "가장"현대적인 데스크탑 시스템에서 "즉시"작동하는 스크립트 파일을 만드는 것입니다. Windows 7/8/10, Ubuntu, OSX ... shebangless 스크립트의 해결 방법은 어느 정도입니까? 궁금해? 어쨌든, 나는 나 자신에게 포인트를 수여하지 않을 것이다 :-)
jez

나는 대답과 질문이 같은 사람에 의해 쓰여진 것을 보지 못했습니다. 내가 작업 한 모든 쉘에 누락 된 #!줄 에 대한 해결 방법이 있다고 생각 하지만 스크립트를 해석하기 위해 다른 쉘을 사용합니다. 즉, 시작하지 않는 "스크립트" #!는 하나의 쉘에서만 유효해야하며, 그럴듯하게 해석 할 수있는 모든 쉘에서 유효해야합니다. 그러나 더 나쁜 것은 다른 쉘에서 시작할 때만 작동합니다. 이러한 스크립트는 명령 행에서 작동하지만 최종적으로 사용하려는 컨텍스트에서는 작동하지 않습니다.
kasperd

감사합니다. 이것은 매우 교육적인 내용이며이 도전을 시작하여 제가 배우고 싶었던 것과 정확히 일치합니다. 이것이 (또는) 중요 할 경우 #!편집 된 답변 (21 인프라 문자가있는 1 인프라 라인)의 줄을 Windows 전용 크래프트 비용 2 줄 (빈 줄) 또는 다른 사람의 답변과 결합 할 수 있습니다. 23 자
jez December

2

답변과 토론의 요약 / 합성

재미 있었고 많은 것을 배웠습니다.

POSIX 시스템에서 스크립트를 한 #!줄로 시작해야하는 경우 일부 Windows 관련 크래프트가 불가피합니다 . 대안이 없다면이 행을 수행하십시오.

#!/bin/sh # 2>NUL

아마 그것이 얻을 수있는 최선일 것입니다. 하나의 빈 줄과 한 줄의 꺽쇠가 Windows 콘솔에서 출력됩니다. 그러나, 당신 없이 도망 갈 수 있습니다#! 줄 : - 그것은에 따라 다르지만 것입니다 대부분의 시스템에서, 일반적인 쉘 인터프리터 중 하나가 스크립트를 실행 끝날 것이다 (문제는이 될 것이다 통역 보편적으로 예측할 수없는 점이다 명령을 호출하는 데 사용하는 쉘과 반드시 ​​동일 할 필요는 없습니다.

그 까다로운 첫 줄을 넘어서, 정말 독창적 인 무자비한 해결책이있었습니다. jimmy23013 의 수상작 은 단 두 개의 짧은 인프라 라인으로 구성 :되었으며 두 플랫폼 모두에서 "사일런트"라인을 구현하기 위해 캐릭터 의 이중 역할을 사용했습니다 ( 사실상sh 친구가 아닌 친구 및 레이블로). 의 마커 cmd.exe) :

:<<@exit/b

:: Arbitrary Windows code goes here

@exit/b
#
# Arbitrary POSIX code goes here 

이다 심지어 CRLF 라인 결말에도 불구하고 POSIX 시스템에서 이러한 스크립트의 실행을 위해,하지만 당신은 종료가 가장 통역이 작업을 수행 할 수 있는 모든 코멘트 나 주석 문자와 POSIX 부분의 라인 (심지어 빈 줄을).

마지막으로 모든 사람의 입력을 기반으로 개발 한 솔루션의 두 가지 변형이 있습니다. 그들은 거의 모든 세계에서 최고 일 수 있습니다 #!. 두 개의 추가 인프라 라인이 필요합니다. 예측할 수없는 POSIX 셸에서 하나의 (표준화 된) 줄만 해석하면되며이 줄을 통해 나머지 스크립트 ( bash다음 예에서)에 대한 셸을 선택할 수 있습니다 .

:<<@GOTO:Z

@echo Hello Windows!

@GOTO:Z
bash "$@"<<:Z
#
echo "Hello POSIX!" #
ps # let's throw this into the payload to keep track of which shell is being used
#
:Z

이 heredoc 솔루션의 장점 중 하나는 여전히 CRLF에 강하다는 <<:Z것 입니다. 라인 의 끝에 오는 한 heredoc 프로세서는 실제로 토큰을 찾고 찾을 것입니다.:Z\r

마지막으로 \r, 행을 쉘로 전달하기 전에 문자 를 제거하여 성가신 줄 끝 주석을 제거하고 CRLF 견고성을 유지할 수 있습니다. 이것은 예측할 수없는 쉘에 약간 더 많은 믿음을 부여합니다 ( { tr -d \\r|bash;}대신 사용 하는 것이 (tr -d \\r|bash)좋지만 중괄호는 bash 전용 구문입니다).

:<<@GOTO:Z

@echo Hello Windows!

@GOTO:Z
(tr -d \\r|bash "$@")<<:Z

echo "Hello POSIX!"
ps

:Z

물론이 방법은 stdin 입력을 스크립트에 파이프하는 기능을 희생합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.