여러 파일이 있는 디렉터리가 있는데 그 중 일부는 bash 스크립트이지만 파일 이름에 .sh 확장명이 포함되어 있지 않습니다. -type 옵션으로 파일 형식을 확인하려면 file 명령을 사용해야 한다는 것과 xargs를 사용하여 출력을 리디렉션하여 파일 이름을 원래 이름 + .sh 확장자로 바꿀 수 있다는 것도 알고 있습니다. 문제는 모든 명령을 함께 연결하는 방법이나 bash ASCII 텍스트 전용 실행 파일의 파일 형식을 찾는 방법을 모른다는 것입니다. 간단한 명령으로 이 작업을 수행하는 방법을 아시나요?
답변1
표준 shebang 라인을 설정하면 file
(최소 버전 5.39) 이를 감지할 수 있어야 합니다.
$ echo '#!/usr/bin/env bash' > 1
$ echo '#!/bin/bash' > 2
$ echo '#!/usr/bin/bash' > 3
$ file *
1: Bourne-Again shell script, ASCII text executable
2: Bourne-Again shell script, ASCII text executable
3: Bourne-Again shell script, ASCII text executable
그래서 우리는 이것을 할 수 있어야 합니다:
for path in ./*
do
if [[ "$(file "$path")" = "${path}: Bourne-Again shell script, ASCII text executable" ]]
then
mv "$path" "${path}.bash"
fi
done
이는 위의 예제 파일에서 작동합니다(그리고 공백 문자를 포함하거나 하이픈으로 시작하거나 개행 문자로 끝나는 파일 이름을 포함하여 특이한 파일 이름에도 작동해야 합니다).
$ ls
1.bash 2.bash 3.bash
이건 아마도아니요이것은 파일에 shebang 줄이 없는 경우에 작동합니다(이는 다음과 같은 파일에 적합합니다).다른 스크립트에서 얻음또는 shebang 줄이 잘못되었습니다(예:#!/bin/sh
).
(저는 ".sh"보다 더 명시적이기 때문에 ".bash"를 사용했습니다.)
답변2
find
이것이 작업을 수행하지는 않지만 kann이 grep
파일 디렉토리를 재귀적으로 검색할 필요는 없습니다 -r
(파일 이름이 와일드카드를 통해 전달되는 경우에도 해당).
grep -lIw '^#!.*bash' dir/!(*.sh) | xargs -I_ mv _ _.sh
grep-r
목차모든 하위 디렉터리의 모든 파일을 검색합니다(여기에서는 사용되지 않음).
grep은 일치하는 각 파일 이름을 인쇄하는 -l
것과 유사 -H
하지만 일반 출력을 억제합니다. 또한 첫 번째 일치 후에는 -q
또는 유사하게 중지됩니다.-m1
grep은 -I
바이너리 파일을 제외하고 텍스트 파일만 처리합니다.
grep-w
세게 때리다전체 단어만 일치합니다(일치하지 않음).세게 때리다편집하다)
정규식^
#!줄의 시작 부분만 일치합니다(#과 일치하지 않음).#!)
모든 바이트 = 모든 문자열 .
과 일치하는 정규식*
.*
경로 이름 확장(와일드카드) *.sh
이 file.sh 패턴과 일치합니다.
확장된 와일드카드는 !(pattern)
패턴을 제외한 모든 항목과 일치합니다.
ls는 dir/!(*.sh)
모든 파일을 나열합니다목차들어오지 못하게 하다디렉토리/file.sh문서
매개변수-I
무늬매개변수는 각 위치에 삽입됩니다.무늬_
이 예에서는 다음을 사용합니다.
mv _ _ .sh
mv file1 file1.sh
mv file2 file2.sh