bash 스크립트에서 파일 이름의 확장자를 확인하는 방법은 무엇입니까?


169

bash에서 야간 빌드 스크립트를 작성 중입니다.
하나의 작은 걸림돌을 제외하고는 모든 것이 훌륭하고 멋집니다.


#!/bin/bash

for file in "$PATH_TO_SOMEWHERE"; do
      if [ -d $file ]
      then
              # do something directory-ish
      else
              if [ "$file" == "*.txt" ]       #  this is the snag
              then
                     # do something txt-ish
              fi
      fi
done;

내 문제는 파일 확장자를 결정하고 그에 따라 행동하는 것입니다. 문제가 if 문에 있고 txt 파일을 테스트하고 있음을 알고 있습니다.

파일에 .txt 접미사가 있는지 어떻게 알 수 있습니까?


이름에 공백이있는 파일이 있으면 중단됩니다.
jfg956

바울의 대답 이외에, 당신은 사용할 수 있습니다 $(dirname $PATH_TO_SOMEWHERE)$(basename $PATH_TO_SOMEWHERE)분할에 폴더와 디렉토리와 무언가 디렉토리 틱 및 파일 틱
McPeppr

답변:


248

"$ file의 마지막 네 문자는 .txt?와 같 습니까?" 그렇다면 다음을 사용할 수 있습니다.

if [ ${file: -4} == ".txt" ]

':-'수정자는 다른 것을 의미하므로 file:와 사이에 공백 -4이 필요합니다.


1
이를 위해 Windows 시스템에서도 command.com의 이름을 command.txt로 바꿀 수 있습니다.
hometoast 2018 년

9
부등식을 지정하려면 추가 대괄호를 포함해야합니다. if [[$ {file : -4}! = ".txt"]]
Ram Rajamony

4
@RamRajamony 불평등을 테스트 할 때 [[]를 사용해야하는 이유는 무엇입니까?
PesaThe

콜론 뒤의 공간이 중요하다는 점을 지적하고 싶었습니다. ${var:-4}와 동일하지 않습니다 ${var: -4}. var가 설정되지 않은 경우 첫 번째 (공백없이)는 '-4'로 확장됩니다. 두 번째 (공백 포함)는 var의 마지막 4자를 반환합니다.
pbatey

1
bash에서는 첫 변수 주위에 따옴표를 넣지 않으면 "[: == : 단항 연산자 예상"오류가 발생합니다. 그래서 if [ "${file: -4}" == ".txt" ]대신.
Giles B

264

하다

if [ "$file" == "*.txt" ]

이처럼 :

if [[ $file == *.txt ]]

즉, 큰 괄호와 따옴표는 없습니다.

오른쪽 ==은 쉘 패턴입니다. 정규식이 필요하면 =~then을 사용하십시오 .


15
나는 이것에 대해 몰랐다. == 또는! =의 오른쪽이 쉘 패턴으로 확장되는 특별한 경우 인 것 같습니다. 개인적으로 나는 이것이 내 대답보다 명확하다고 생각합니다.
Paul Stephenson

20
나는 bash를 처음 접했고 다중 조건문에서 이것을 사용하는 방법을 알아내는 데 약간의 시간이 걸렸다 if. 누군가를 도울 수 있도록 여기에서 공유하고 있습니다. if [[ ( $file == *.csv ) || ( $file == *.png ) ]]
joelostblom

6
@cheflo 일반적으로 여러 조건에 적합합니다. 이 경우에는을 사용할 수도 있습니다 if [[ $file =~ .*\.(csv|png) ]]. 더 짧고, 명확하고, 추가 확장을 쉽게 추가 할 수 있으며, 변수에 "csv | png"를 넣어서 쉽게 구성 할 수 있습니다.
jox

4
파일 주위에 큰 따옴표를 넣을 수 있습니다. if [[ "$file" == *.txt ]]파일 이름에 공백이 있으면 큰 따옴표가 필요합니다.
shawnhcorey

수락 된 답변 대신이 답변을 사용해야합니까?
Freedo

26

유닉스 시스템에서는 .txt 파일이 텍스트 파일이라는 것을 확신 할 수 없습니다. 최선의 방법은 "파일"을 사용하는 것입니다. 아마도 다음을 사용하십시오.

file -ib "$file"

그런 다음 "텍스트", "응용 프로그램"등과 같은 항목을 얻는 MIME의 첫 번째 부분과 일치하거나 구문 분석하기 위해 MIME 유형 목록을 사용할 수 있습니다.


2
으로 file -i...마임 인코딩을 포함, 당신은 사용할 수 있습니다file --mime-type -b ...
윌프

24

실제로 확장자에 의존하지 않고 파일에 대한 정보를 찾으려면 "file"명령을 사용할 수 있습니다.

확장 기능을 사용하는 것이 편한 경우 grep을 사용하여 확장 기능이 일치하는지 확인할 수 있습니다.


예, file명령을 알고 있습니다. 나는 실제로 말했다 명령의 출력을 기반으로 일치를 시도했지만 ...이 if 문에서 끔찍하게 실패합니다.

17

당신은 또한 할 수 있습니다 :

   if [ "${FILE##*.}" = "txt" ]; then
       # operation for txt files here
   fi

11
case $FILE in *.txt ) ... ;; esac더 강력하고 관용적으로 보일 것입니다.
tripleee

11

'file'과 유사하게, 파일 확장자에 관계없이 약간 더 간단한 'mimetype -b'를 사용하십시오.

if [ $(mimetype -b "$MyFile") == "text/plain" ]
then
  echo "this is a text file"
fi

편집 : mimetype을 사용할 수없는 경우 시스템에 libfile-mimeinfo-perl을 설치해야 할 수도 있습니다


1
'mimetype'스크립트가 모든 시스템에서 사용 가능한 것은 아님을 분명히해야합니다.
gilbertpilz 2014 년

libfile-mimeinfo - 펄 추가, 완료
dargaud

5

리눅스에서 파일 이름으로 확장자를 얻는 방법에 대한 정답은 다음과 같습니다.

${filename##*\.} 

디렉토리의 모든 파일 확장자를 인쇄하는 예

for fname in $(find . -maxdepth 1 -type f) # only regular file in the current dir
    do  echo ${fname##*\.} #print extensions 
done

답은 이중 백 슬래시를 사용하지만 예제는 단일 백 슬래시 만 사용합니다. 당신의 예는 정확하고 대답은 정확하지 않습니다.
gilbertpilz 2014 년

3

파일 형식을 확인한 다음 파일을 위치에 복사하는 bash 스크립트를 작성했습니다.이 파일을 사용하여 파이어 폭스 캐시에서 온라인으로 본 비디오를 봅니다.

#!/bin/bash
# flvcache script

CACHE=~/.mozilla/firefox/xxxxxxxx.default/Cache
OUTPUTDIR=~/Videos/flvs
MINFILESIZE=2M

for f in `find $CACHE -size +$MINFILESIZE`
do
    a=$(file $f | cut -f2 -d ' ')
    o=$(basename $f)
    if [ "$a" = "Macromedia" ]
        then
            cp "$f" "$OUTPUTDIR/$o"
    fi
done

nautilus  "$OUTPUTDIR"&

여기에 제시된 것과 비슷한 아이디어를 사용합니다. 이것이 누군가에게 도움이되기를 바랍니다.


2

나는 그 생각 '$PATH_TO_SOMEWHERE'같은 것입니다 '<directory>/*'.

이 경우 코드를 다음과 같이 변경합니다.

find <directory> -maxdepth 1 -type d -exec ... \;
find <directory> -maxdepth 1 -type f -name "*.txt" -exec ... \;

디렉토리 및 텍스트 파일 이름으로 더 복잡한 작업을 수행하려는 경우 다음을 수행 할 수 있습니다.

find <directory> -maxdepth 1 -type d | while read dir; do echo $dir; ...; done
find <directory> -maxdepth 1 -type f -name "*.txt" | while read txtfile; do echo $txtfile; ...; done

파일 이름에 공백이 있으면 다음을 수행 할 수 있습니다.

find <directory> -maxdepth 1 -type d | xargs ...
find <directory> -maxdepth 1 -type f -name "*.txt" | xargs ...

다음은 쉘에서 '루프'를 수행하는 방법에 대한 훌륭한 예입니다. 루프 본문이 더 복잡해야 할 때 명시 적 forwhile루프를 더 잘 예약합니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.