파일 이름으로 확장자를 잡아 위해의 단일 명령으로

bash에서 파일 확장자를 어떻게 얻습니까? 내가 시도한 것은 다음과 같습니다.

filename=`basename $filepath`
fileext=${filename##*.}

그렇게 bz2하면 경로에서 확장을 얻을 수 /dir/subdir/file.bz2있지만 경로 에 문제가 /dir/subdir/file-1.0.tar.bz2있습니다.

가능하다면 외부 프로그램없이 bash 만 사용하는 솔루션을 선호합니다.

내 질문을 분명히하기 위해의 단일 명령으로 주어진 아카이브를 추출하는 bash 스크립트를 작성했습니다 extract path_to_file. 그것의 압축을 보거나 유형을 보관하여 스크립트에 의해 결정되는 방법 파일을 추출하는 방법, 그게 내가 확장을받을 경우 .bz2로 등 I 예를 들어,이 문자열 조작을 포함해야한다 생각에 .gz, .tar.gz를 할 수 .gz그때 .tar앞에 문자열이 있는지 확인 .gz해야합니다 .tar.gz. 확장명은이어야합니다 .



답변

파일 이름이 file-1.0.tar.bz2인 경우 확장자는 bz2입니다. 확장명 ( fileext=${filename##*.}) 을 추출하는 데 사용하는 방법 은 완벽하게 유효합니다 ¹.

당신은 어떻게 당신이 확장 될 것인지로 결정 tar.bz2하지 bz20.tar.bz2? 이 질문에 먼저 답해야합니다. 그런 다음 사양에 맞는 쉘 명령을 알아낼 수 있습니다.

  • 가능한 사양 중 하나는 확장자가 문자로 시작해야한다는 것입니다. 이 휴리스틱은와 같은 몇 가지 일반적인 확장에 실패 7z하며 특수 사례로 가장 잘 처리 될 수 있습니다. bash / ksh / zsh 구현은 다음과 같습니다.

    basename=$filename; fileext=
    while [[ $basename = ?*.* &&
             ( ${basename##*.} = [A-Za-z]* || ${basename##*.} = 7z ) ]]
    do
      fileext=${basename##*.}.$fileext
      basename=${basename%.*}
    done
    fileext=${fileext%.}

    POSIX 이식성을 case위해 패턴 일치를위한 명령문 을 사용해야합니다 .

    while case $basename in
            ?*.*) case ${basename##*.} in [A-Za-z]*|7z) true;; *) false;; esac;;
            *) false;;
          esac
    do 
  • 또 다른 가능한 사양은 일부 확장은 인코딩을 나타내며 추가 스트리핑이 필요하다는 것을 나타냅니다. bash / ksh / zsh 구현은 다음과 같습니다 ( shopt -s extglobbash 및 setopt ksh_globzsh 아래 필요 ).

    basename=$filename
    fileext=
    while [[ $basename = ?*.@(bz2|gz|lzma) ]]; do
      fileext=${basename##*.}.$fileext
      basename=${basename%.*}
    done
    if [[ $basename = ?*.* ]]; then
      fileext=${basename##*.}.$fileext
      basename=${basename%.*}
    fi
    fileext=${fileext%.}

    0의 확장명으로 간주 됩니다 file-1.0.gz.

¹ 및 관련 구문은 POSIX 에 있으므로 ash, bash, ksh 또는 zsh와 같은 비 앤티크 (Anti-Anquene) Bourne 스타일 쉘에서 작동합니다.

${VARIABLE##SUFFIX}


답변

확장명을 두 번 추출하는 대신 파일 이름에 패턴 일치를 수행하여 문제를 단순화 할 수 있습니다.

case "$filename" in
    *.tar.bz2) bunzip_then_untar ;;
    *.bz2)     bunzip_only ;;
    *.tar.gz)  untar_with -z ;;
    *.tgz)     untar_with -z ;;
    *.gz)      gunzip_only ;;
    *.zip)     unzip ;;
    *.7z)      do something ;;
    *)         do nothing ;;
esac


답변

$ echo "thisfile.txt"|awk -F . '{print $NF}'

여기에 대한 의견 : http://liquidat.wordpress.com/2007/09/29/short-tip-get-file-extension-in-shell-script/


답변

여기에 내 장면이 있습니다 : 점을 줄 바꿈으로 변환하고을 통과 tail하고 마지막 줄을 얻으십시오.

$> TEXT=123.234.345.456.456.567.678
$> echo $TEXT | tr . \\n | tail -n1
678


답변

echo ${filename#$(echo $filename | sed 's/\.[^[:digit:]].*$//g;')}

예를 들면 다음과 같습니다.

% echo $filename
2.6.35-zen2.patch.lzma
% echo ${filename#$(echo $filename | sed 's/\.[^[:digit:]].*$//g;')}
.patch.lzma


답변

어느 날 나는 그 까다로운 기능을 만들었습니다.

# args: string how_many
function get_last_letters(){ echo ${1:${#1}-$2:$2}; }
function cut_last_letters(){ echo ${1:0:${#1}-$2}; }

확장에 관한 것뿐만 아니라 많은 경우에 매우 유용한이 간단한 접근 방법을 찾았습니다.

확장 프로그램 확인- 간단하고 안정적 ​​임

~$ get_last_letters file.bz2 4
.bz2
~$ get_last_letters file.0.tar.bz2 4
.bz2

절단 연장 용 :

~$ cut_last_letters file.0.tar.bz2 4
file.0.tar

확장명 변경 :

~$ echo $(cut_last_letters file.0.tar.bz2 4).gz
file.0.tar.gz

또는 “유용한 기능 :

~$ function cut_last_letters_and_add(){ echo ${1:0:${#1}-$2}"$3"; }
~$ cut_last_letters_and_add file.0.tar.bz2 4 .gz
file.0.tar.gz

추신 : 당신이 그 기능을 좋아하거나 그 기능이 충분히 사용 된 것을 발견했다면,이 게시물을 참조하십시오 :).


답변

jackman case-based answer은 꽤 훌륭하고 이식 가능하지만 변수의 파일 이름과 확장자를 원한다면이 솔루션을 찾았습니다.

INPUTFILE="$1"
INPUTFILEEXT=$( echo -n "$INPUTFILE" | rev | cut -d'.' -f1 | rev )
INPUTFILEEXT=$( echo -n $INPUTFILEEXT | tr '[A-Z]' '[a-z]' ) # force lowercase extension
INPUTFILENAME="`echo -n \"$INPUTFILE\" | rev | cut -d'.' -f2- | rev`"

# fix for files with multiple extensions like "gbamidi-v1.0.tar.gz"
INPUTFILEEXT2=$( echo -n "$INPUTFILENAME" | rev | cut -d'.' -f1 | rev )
if [ "$INPUTFILEEXT2" = "tar" ]; then
    # concatenate the extension
    INPUTFILEEXT="$INPUTFILEEXT2.$INPUTFILEEXT"
    # update the filename
    INPUTFILENAME="`echo -n \"$INPUTFILENAME\" | rev | cut -d'.' -f2- | rev`"
fi

이중 확장에서만 작동하며 첫 번째 확장은 “tar”여야합니다.

그러나 문자열 길이 테스트로 “tar”테스트 라인을 변경하고 수정을 여러 번 반복 할 수 있습니다.