다음과 같은 파일이 있는 경우
#!/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
하지만 bash
NUL로 시작하고 다음에 #!
읽는 파일에 대해서는 오탐지를 제공합니다.모두예를 들어 선행 NUL 바이트는 truncate -s1T file
한 번에 완전히 2바이트로 생성된 1테비바이트 파일을 읽습니다.
따라서 bash
다음을 사용하는 것이 더 좋습니다.
IFS= LC_ALL=C read -rn2 -d '' shebang
읽혀진 것까지NUL로 구분된 레코드의 2바이트입니다.
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 스파스 파일을 사용하면 대부분의 셸에서 많은 시간이 소요됩니다(그리고 잠재적으로 많은 메모리를 사용하게 됩니다).
가 아닌 다른 쉘을 사용하면 zsh
NUL로 시작하고 뒤에 #!
.
쉘을 사용하면 yash
shebang에 현재 로케일에서 유효한 문자를 형성하지 않는 바이트 시퀀스가 포함되어 있으면 실패합니다(shebang에 C 로케일에 ASCII가 아닌 문자가 포함되어 있으면 실패할 수도 있습니다(적어도 2.39 이상에서는). 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=raw
perl
IO 버퍼링 계층 없이 직접 시스템 호출을 사용하게 하므로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
0x2123
16진수는 '#!'입니다. 역순으로:
$ 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