최종 스크립트

최종 스크립트

파일로 가득 찬 디렉토리가 있습니다. 내 목표는 파일 시작 부분에 텍스트를 추가하는 것입니다. 각 파일의 시작 부분에 있는 텍스트는 동일합니다. 이게 내 시도야

#!/bin/bash                                                                                                                                                    

for file in `find . -type f -executable`;do                                                                                                                                 
    sed '/\#!/bin/bash\/a Hello Word'                                                                                                                                            


done

내 스크립트는 충돌만 발생합니다.

답변1

#!/bin/bash

for file in `find . -type f -executable`;do
    sed '/\#!/bin/bash\/a Hello Word'
fi

done

이 스크립트에는 많은 문제가 있습니다.


첫째, fi해당 if.


스타일상( fi줄을 제거한 후) 앞의 빈 줄을 제거 done하고 그 앞에 공백을 추가합니다 do. 그러나 이것은 상대적으로 사소한 일이다.


이제 모범 사례에 따르면 권장되는 최신 형식 대신 백틱을 사용하여 명령을 대체합니다 $(...). 백틱에 대한 지원은 순전히 역사적인 이유로 권장되지 않습니다.


출력을 반복하기 때문에 견고성 문제가 있습니다 find. 이는 매우 나쁜 생각이고 완전히 불필요한 것입니다. 공백이나 특수 문자가 포함된 파일 이름에서 스크립트가 중단됩니다. 바라보다:


스크립트를 이식 가능하게 하려면 가능하면 POSIX에 지정된 기능을 고수해야 합니다. 특히 -executable가장 중요한 find것은POSIX가 지정되지 않았습니다.. 대신 사용해 보세요 -perm +700.

또한 이식성 영역에서 a다음 \<newline>순서 없이 Sed()를 사용하는 GNU Sed의 "추가" 명령은 작동하지만 표준은 아닙니다.


file루프 의 변수를 각 파일의 이름으로 차례로 설정합니다 ( for파일 이름에 특수 문자나 공백이 없다고 가정하면 변수에 file다음이 포함됩니다).아니요파일 이름), 하지만 실제로는사용변수 file.

Sed 명령은 실행할 파일을 제공하지 않으므로 표준 입력에서 실행을 시도합니다. 따라서 스크립트를 실행하면 입력을 기다립니다.


Sed 스크립트 자체가 올바르지 않으며 작동할 파일 이름이 없다는 사실과 아무 관련이 없습니다.

/정규 표현식(가장 일반적임)에서 구분 기호 로 사용하는 경우 /정규 표현식에서 해당 문자가 나오는 모든 항목을 백슬래시로 이스케이프 처리해야 합니다. 명령의 유일한 부분은 정규식으로 읽히고 /\#!/나머지 부분(이로 시작하는 부분 bin)은 Sed 명령으로 해석됩니다.

대신, 일반적인 해결책은 각각을 교체하는 것입니다./ 다른최종 정규식 구분 기호보다 \/(이스케이프된 것 같습니다.오직마지막 슬래시는아니요탈출했습니다. )

하나 있다Sed의 잘 알려지지 않은 기능,여기서 이것을 유리하게 활용할 수 있습니다. 어느백슬래시나 개행 문자 이외의 문자는 슬래시뿐만 아니라 정규식 구분 기호로 사용할 수 있습니다. 따라서 이를 /#!\/bin\/bash/Sed 주소 로 사용하는 대신 동등한 주소를 사용할 수 있습니다.\:#!/bin/bash:


이제 위의 모든 사항을 처리했다면 작동하는 스크립트가 생겼을 것입니다. 아마 당신이 원하는 대로 되지 않을 거예요생각하다그렇게 해야 하지만 실제로는 그렇게 될 것입니다.뭔가를 해라. 이러한 스크립트는 다음과 같습니다.

#!/bin/bash

find . -type f -perm -700 -exec sed '\:#!/bin/bash:a\
Hello World' {} +

이 스크립트는 무엇을 합니까? 현재 디렉터리에서 실행 가능 비트(소유자)가 설정된 모든 파일을 반복적으로 검색하고, 이러한 각 파일에 대해 전체 파일을 인쇄하고 Hello Worldtext 가 포함된 줄 뒤에 텍스트를 추가합니다 #!/bin/bash.

sed는 실제로는 아닙니다디자인됨파일을 제자리에서 편집하는 데 사용됩니다. 스트림 편집기입니다. GNU Sed에서는 스위치를 사용하여 파일을 편집할 수 있지만 -i저는 그냥 다음을 사용하겠습니다.표준 도구ex파일 편집에 사용됩니다.


하지만 여기에는 다른 것이 있습니다. Bash 스크립트에 해당 줄을 추가 하려는 경우 유효한 명령 이름이 아니기 Hello World때문에 실제로 아무 작업도 수행되지 않습니다 . Hello아마도 당신이 원하는 것은인쇄Bash 스크립트에 "Hello World"라는 텍스트를 추가하는 것이 echo "Hello World합리적일 수 있습니다 .

이제 우리는 귀하의 스크립트가 무엇인지 더 정확하게 설명하고 싶습니다.~해야 한다해.


최종 스크립트

따라서 이 스크립트의 사양에 대한 보다 정확한 설명은 다음과 같습니다.

  • 이 스크립트는 소유자에 대해 실행 가능한 비트가 설정된 현재 디렉터리(또는 재귀적으로 모든 하위 디렉터리)에서 모든 일반 파일을 찾아야 합니다.
  • 이러한 각 파일에 대해 스크립트는 파일의 첫 번째 줄이 문자열과 정확히 동일한지 확인해야 합니다 #!/bin/bash.
  • 정확한 첫 번째 줄이 있는 파일의 경우에만 스크립트는 echo "Hello World"파일의 첫 번째 줄 뒤에 정확한 텍스트를 삽입하고 그 뒤에 개행 문자를 삽입해야 합니다. (이 변경 사항은 표준 출력으로 인쇄하기보다는 파일에 저장해야 합니다.)

다음은 POSIX 도구와 기능만 사용하여 정확한 사양을 준수하는 스크립트입니다.

#!/bin/sh

find . -type f -perm -700 -exec sh -c '
  for f
  do
    head -n 1 "$f" | grep -qFx "#!/bin/bash" &&
      printf "%s\n" "1a" "echo \"Hello World\"" . x | ex "$f"
  done
' find-sh {} +

답변2

무엇을 달성하고 싶나요? 실행 가능한 스크립트를 찾으려면 다음 명령을 사용하십시오.

find . -type f -perm /u+x,g+x,o+x | while read file
do
    filename=$(echo ${file} | awk -F/ '{print $NF}')
    echo "File Name : ${filename}"
done

Shebang 줄 뒤에 Hello World를 추가하려고 하면 sed 명령은 다음과 같아야 합니다.

 sed '/\#!/bin/bash/a Hello Word' ${file}

파일 자체를 변경하려면 sed 명령에 -i를 추가하세요.

답변3

find . -type f -executable -exec sed '/^#!\/bin\/bash/a Hello World' {} \;

관련 정보