shebang이 존재하는지 확인하는 가장 빠른 방법

shebang이 존재하는지 확인하는 가장 빠른 방법

파일이 있으면

#!/usr/bin/env foobar

파일에 해시뱅이 있는지 확인하는 가장 빠르고 최선의 방법은 무엇입니까? 처음 2바이트만 읽을 수 있다고 들었는데? 어떻게?

답변1

그리고 zsh:

if LC_ALL=C read -u0 -k2 shebang < file && [ "$shebang" = '#!' ]; then
  echo has shebang
fi

또는와 ksh93동일 bash:

if IFS= LC_ALL=C read -rN2 shebang < file && [ "$shebang" = '#!' ]; then
  echo has shebang
fi

그러나 NUL로 시작하고 그 뒤에 and가 오는 파일에는 bash오탐지가 발생합니다 .#!모두truncate -s1T file예를 들어, 선행 NUL 바이트는 한 번에 2바이트로 생성된 1테비바이트 파일을 읽습니다.

따라서 bash다음을 사용하는 것이 좋습니다.

IFS= LC_ALL=C read -rn2 -d '' shebang

내가 읽은 게 바로 그거야에 따라2바이트 NUL로 구분된 레코드입니다.

read[명령이 echo내장되어 있으므로 프로세스를 포크하거나 추가 명령을 실행하지 않습니다 .

POSIXly에서는 다음과 같이 할 수 있습니다.

if IFS= read -r line < file; then
  case $line in
    ("#!"*) echo has shebang
  esac
fi

완전한 라인도 필요하기 때문에 더 엄격합니다. 적어도 Linux에서는 유효한 shebang에 개행 문자가 필요하지 않습니다.

그래서 당신은 이것을 할 수 있습니다 :

line=
IFS= read -r line < file
case $line in
  ("#!"*) echo has shebang
esac

더 많은 바이트를 읽을 수 있기 때문에 약간 덜 효율적이지만 일부 쉘은 한 번에 1바이트만 읽을 수 있습니다. 1TiB 스파스 파일의 경우 대부분의 셸에서 시간이 많이 걸리고 메모리도 많이 사용하게 됩니다.

이것 이외의 쉘의 경우 zshNUL로 시작하고 뒤에 오는 문자에 응답할 수도 있습니다 #!.

쉘 의 경우 yashshebang에 현재 로케일에서 유효한 문자를 형성하지 않는 바이트 시퀀스가 ​​포함되어 있으면 실패합니다(shebang에 C 로케일(적어도 2.39 및 이전 버전)에서 ASCII가 아닌 문자가 포함되어 있는 경우에도 실패합니다. C 로케일은 모든 문자가 단일 바이트이고 모든 바이트 값이 유효한(반드시 정의되지 않은 경우) 문자를 형성한다는 것을 의미하지만)

내용이 로 시작하는 모든 파일을 찾으려면 #!다음을 수행할 수 있습니다.

PERLIO=raw find . -type f -size +4c -exec perl -T -ne '
  BEGIN{$/=\2} print "$ARGV\n" if $_ eq "#!"; close ARGV' {} +

우리는 크기가 최소 5바이트( #!/x\n가장 작고 현실적인 shebang)인 파일만 고려합니다.

  • 를 사용하여 -exec perl... {} +가능한 한 많은 파일 경로를 전달하므로 perl가능한 적은 호출을 실행합니다.
  • -T해결될 예정이다한계perl -n또한 ASCII 공백 문자 또는 .로 끝나는 이름에는 작동하지 않음을 의미합니다 |.
  • PERLIO=rawperlIO 버퍼링 계층 없이 시스템 호출이 직접 사용되도록 하므로 read()(파일 이름 인쇄에도 영향을 미침) 크기 2의 읽기를 수행합니다.
  • $/ = \2레코드 구분 기호가 숫자에 대한 참조로 설정되면 레코드가 고정 길이 레코드가 됩니다.
  • close ARGV첫 번째 레코드를 읽은 후 현재 파일의 나머지 부분을 건너뜁니다.

답변2

자신만의 "마법 패턴"을 정의 /etc/magic하고 이를 file테스트에 사용할 수 있습니다.

$ sudo vi /etc/magic
$ cat /etc/magic
# Magic local data for file(1) command.
# Insert here your local magic data. Format is described in magic(5).
0 byte 0x2123 shebang is present
$ cat /tmp/hole2.sh #To prove [1] order of hex [2] 2nd line ignored
!#/bin/bash 
#!/bin/bash
$ cat /tmp/hole.sh 
#!/bin/bash
$ file /tmp/hole2.sh 
/tmp/hole2.sh: ASCII text
$ file /tmp/hole.sh 
/tmp/hole.sh: shebang is present
$ file -b /tmp/hole.sh #omit filename
shebang is present

0x212316진수 "#!"은 역순입니다.

$ ascii '#' | head -n1
ASCII 2/3 is decimal 035, hex 23, octal 043, bits 00100011: prints as `#'
$ ascii '!' | head -n1
ASCII 2/1 is decimal 033, hex 21, octal 041, bits 00100001: prints as `!'

다음을 배치하도록 선택할 수 있습니다.

0 string \#\! shebang is present

인용하다: man 5 magic, man 1 file, man 1posix file

답변3

다음을 수행해야 합니다.

if [ "`head -c 2 infile`" = "#!" ]; then
    echo "Hashbang present"
else
    echo "no Hashbang present"
fi

답변4

grep단일 라인 솔루션 용

if head -1 file | grep "^#\!" > /dev/null;then echo "true"; fi

관련 정보