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
하지 bz2
나 0.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 extglob
bash 및setopt ksh_glob
zsh 아래 필요 ).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”테스트 라인을 변경하고 수정을 여러 번 반복 할 수 있습니다.