여러 개의 가능한 접미사 제거

여러 개의 가능한 접미사 제거

예: 이미지를 축소하는 빠른 명령을 만들고 싶습니다(내 파일 브라우저용).

...
FN="/tmp/some-image.jpg"
gm convert "$FN" -resize 50% "$(dirname $FN)/$(basename $FN .jpg/png/gif).jpg"
...

둘 이상의 접미사가 제거되도록 지정하려면 어떻게 해야 합니까?

답변1

basename제거할 접미사 하나만 가져오고 어쨌든 원하지 않는 기본 이름(디렉토리 구성 요소 제거)을 제공하므로 basename실제로는 필요에 맞는 도구가 아닙니다.

문자열에서 데이터를 추출하는 전통적인 도구는 다음과 같습니다 expr.

FN_without_extension=$(expr "x$FN" : 'x\(.*\)\.')

그러나 최신 쉘(예 zsh: 모든 POSIX 호환 ...) 에는 이를 위한 연산자가 내장되어 있으므로 요즘에는 거의 필요하지 않습니다 ( bash그리고 몇 가지 문제가 있으므로 피하는 것이 가장 좋습니다).kshashyashshexpr

${var%pattern}

끝에서 패턴과 일치하는 (가장 작은) 부분을 제거합니다.$var

gm convert "$FN" -resize 50% "${FN%.*}.jpg"

쉘에는 확장을 제거하는 연산자가 있거나 있습니다 tcsh. zshZsh:

gm convert $FN -resize 50% $FN:r.jpg

( r을 위한루트 이름).

jpg/png/gif 중 하나인 경우에만 확장자를 제거하려면 더 복잡해지고 쉘에 따라 달라집니다.

와 함께 zsh:

gm convert $FN -resize 50% ${FN%.(jpg|png|gif)}.jpg

와 함께 ksh:

gm convert "$FN" -resize 50% "${FN%.@(jpg|png|gif)}.jpg"

와 함께 bash:

shopt -s extglob
gm convert "$FN" -resize 50% "${FN%.@(jpg|png|gif)}.jpg"

와 함께 expr:

gm convert "$FN" -resize 50% "$(
  expr \( "x$FN" : '\(.*\)\.png$' \| \
          "x$FN" : '\(.*\)\.jpg$' \| \
          "x$FN" : '\(.*\)\.gif$' \| "x$FN" \) : 'x\(.*\)')".jpg

(예, 그것은 복잡하며 의 일부 문제를 해결하기 위한 것입니다 expr).

일부 expr구현에서는 다음과 같이 단순화할 수 있습니다.

expr \( "x$FN" : '\(.*\)\.\(png\|jpg\|gif\)$' \| "x$FN" \) : 'x\(.*\)'

다음을 사용할 수도 있습니다 sed.

FN_without_ext=$(printf '%s\n' "$FN" |
  sed -e '$!b' -e 's/\.png$//;t' -e 's/\.gif$//;t' -e 's/\.jpg$//')

대소문자를 구분하지 않으려면 png/gif/jpg위의 모든 솔루션에서 를 로 바꿀 수 있습니다 [pP][nN][gG].... 일부 쉘/도구는 대소문자를 구분하지 않는 일치도 수행할 수 있습니다.

zsh:

 setopt extendedglob
 FN_without_ext=${FN%.(#i)(gif|png|jpg)}

ksh93:

 FN_without_ext=${FN%.~(i:gif|png|jpg)}

bash:

 shopt -s nocasematch
 LC_ALL=C
 if [[ $FN =~ (.*)\.(gif|png|jpg)$ ]]; then
   FN_without_ext=${BASH_REMATCH[1]}
 else
   FN_without_ext=$FN
 fi

그누 sed:

 FN_without_ext=$(printf '%s\n' "$FN" | sed -r '$s/\.(png|gif|jpg)$//I')

답변2

이것이 트릭을 수행해야합니까? 기본적으로 제거 .mp3또는 확장 입니다 .wav.

$ basename -s .wav $(basename -s .mp3 'some_file.mp3')
some_file
$ basename -s .wav $(basename -s .mp3 'some_file.wav')
some_file
$ basename -s .wav $(basename -s .mp3 'some_file.rs') 
some_file.rs

관련 정보