파일이 있으면
#!/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 스파스 파일의 경우 대부분의 셸에서 시간이 많이 걸리고 메모리도 많이 사용하게 됩니다.
이것 이외의 쉘의 경우 zsh
NUL로 시작하고 뒤에 오는 문자에 응답할 수도 있습니다 #!
.
쉘 의 경우 yash
shebang에 현재 로케일에서 유효한 문자를 형성하지 않는 바이트 시퀀스가 포함되어 있으면 실패합니다(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=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