파일 이름에서 확장자 가져 오기

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

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

그렇게함으로써 경로에서 bz2의 확장자를 얻을 수 있습니다. /dir/subdir/file.bz2,하지만 /dir/subdir/file-1.0.tar.bz2 경로에 문제가 있습니다.

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

제 질문을 명확히하기 위해 extract path_to_file의 단일 명령으로 주어진 아카이브를 추출하는 bash 스크립트를 작성했습니다. 방법 파일을 추출하는 것은 압축 또는 보관 유형 (.tar.gz, .gz, .bz2 등)을보고 스크립트에 의해 결정됩니다. 예를 들어 확장자가 .gz 그런 다음 .gz 앞에 .tar 문자열이 있는지 확인해야합니다. 그렇다면 확장 프로그램은 .tar.gz.

댓글

  • file = " /dir/subdir/file-1.0.tar.bz2

; echo $ {file ## *.}는 여기에 ' .bz2 '를 인쇄합니다. ' 예상되는 출력은 무엇입니까?

  • .tar.bz2
  • 관련 항목이 필요합니다. : Bash에서 파일 이름 및 확장자를 추출합니다 .
  • 답변

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

    확장 프로그램이 iv id =가되도록 어떻게 결정합니까? bz2 또는 0.tar.bz2가 아닌 “e35c7cbf75″>

    입니까? 먼저이 질문에 답해야합니다. 그런 다음 무엇을 파악할 수 있습니다. 쉘 명령이 사양과 일치합니다.

    • 가능한 사양 중 하나는 확장이 문자로 시작해야한다는 것입니다.이 휴리스틱은 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 구현입니다 (bash에서는 shopt -s extglob, zsh에서는 setopt ksh_glob 필요) :

      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%.} 

      여기서는 0file-1.0.gz의 확장으로 간주합니다.

    ¹ ${VARIABLE##SUFFIX} 및 관련 구문은 POSIX 에 있으므로 ash, bash, ksh 또는 zsh와 같은 비 앤티크 Bourne 스타일 쉘에서 작동합니다.

    댓글

    • 마지막 . 토큰 앞의 문자열이 아카이브 유형인지 확인하여 해결해야합니다 (예 : tar).

    반복이 종료되어야합니다.

  • @uray :이 특정 경우에 작동하지만 일반적인 솔루션은 아닙니다 ' . Maciej '의 .patch.lzma 의 예를 고려해보세요. istic은 마지막 . 문자열을 고려하는 것입니다. ' 압축 접미사 (.7z, .bz2, .gz, …), 계속 제거합니다.
  • @NoamM 들여 쓰기에 무엇이 잘못 되었나요? 수정 후에는 ' 확실히 깨졌습니다. 이중 중첩 코드는 단일 중첩 코드와 동일하게 들여 쓰기됩니다.
  • 답변

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

    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/

    댓글

    • .tar.gz 확장자에서 작동하지 않음
    • 음 .tar .gz는 실제로 gzip 파일 내부의 tar이므로 gzip 파일에서 gz 확장자를 제거한다는 의미에서 작동합니다.

    답변

    여기에 내 장면이 있습니다. 점을 줄 바꿈으로 변환하고 tail, 마지막 줄 가져 오기 :

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

    답변

    언젠가 저는 그 까다로운 기능을 만들었습니다.

    # 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 

    PS 이러한 기능이 마음에 들었거나 충분히 사용되었다고 생각한다면, 이 게시물을 참조하십시오 🙂 (그리고 코멘트를 남겨주세요).

    답변

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

    예 :

    댓글

    • 일부 경우에 작동하지 않습니다. ' foo.7z '
    • 따옴표가 필요하며 파일 이름에 백 슬래시가 포함되어 있거나 -로 시작하는 경우 : "${filename#$(printf %s "$filename" | sed 's/\.[^[:digit:]].*$//g;')}"
    • @axel_c : 맞습니다. 저는 ' Maciej와 동일한 사양을 예로 구현했습니다. '가 “문자로 시작”보다 더 나은 경험적 방법은 무엇입니까?
    • @Gilles : 그게 있다고 생각합니다 '는 해결책이 아닙니다.

    답변

    잭맨 사례 기반 답변은 매우 훌륭하고 이식 가능하지만 변수에 파일 이름과 확장자 만 원하는 경우이 솔루션을 찾았습니다.

    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”테스트 행을 변경하고 수정을 여러 번 반복 할 수 있습니다. .

    답변

    다음을 사용하여 해결했습니다.

    filename=`basename $filepath` fileext=${filename##*.} fileext2=${filename%.*} fileext3=${fileext2##*.} if [ "$fileext3" == "tar" ]; then fileext="tar."$fileext fi 

    그러나 이것은 알려진 보관 유형에서만 작동합니다.이 경우에는 tar

    답글 남기기

    이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다