파일 이름의 일부만 대문자로 변환

파일 이름의 일부만 대문자로 변환

쉘 스크립트 프로그램에서 변환된 파일 이름이 아직 존재하지 않는 경우 파일 이름을 대문자로 변환해야 합니다. 이 특별한 경우에는 확장자(있는 경우)를 그대로 두고 기본 이름만 대문자로 변경해야 합니다.

문제를 해결하는 방법은 먼저 기본 이름과 확장자를 별도로 추출하고 tr명령을 사용하여 기본 이름을 대문자로 변환한 다음 확장자와 함께 변경된 기본 이름이 디렉터리에 있는지 확인하는 것입니다.

존재하지 않으면 mv를 사용하여 원본 파일 이름을 대문자 기본 이름으로 변경합니다. 이제 나는 이것이 두 가지 방법으로 이루어질 수 있다고 생각합니다. 첫 번째는 구분 기호로 with (space- period-space)를 expr사용하는 것입니다 .cut.

기본 이름을 추출하는 데 사용하려면 expr(예: 파일 이름 - python1.py또는 에서 phonelist) 다음과 같이 작성했습니다.

basefile=`expr "$filename" : '\(.*\)\.*.*' ` 

0개 이상의 발생을 무시하기 \.*때문에 확장자가 없는 파일 이름에도 사용했지만 이 표현식은 제대로 작동하지 않습니다. 모든 파일 이름에 대해 전체 파일 이름을 그대로 반환합니다.\.*.expr

누구든지 내가 어디에서 잘못되었는지 설명해 주시겠습니까? 또한 expr파일 이름에서 확장자만 추출하는 방법을 제안해 주십시오 .

답변1

쉘이 bashbash 매개변수 확장만 사용하는 경우:

file="aaa.bbb.dat"

name=${file%.*} # delete everything after last dot 
ext=${file##*.} # delete everything up to last dot
upcase=${name^^*}.$ext # uppercase everything

echo "$upcase"
AAA.BBB.dat

더 어려운 사례로 시도:

file="déjà vu . dat "
name=${file%.*} # delete everything after last dot 
ext=${file##*.} # delete everything up to last dot
upcase=${name^^*}.$ext # uppercase everything
echo ":$upcase:"

다음을 제공합니다:

:DÉJÀ VU . dat :

그래서:

  • 결과를 사용할 때까지 큰따옴표는 필요하지 않습니다.
  • ASCII가 아닌 문자에도 대문자는 괜찮은 것 같습니다.

답변2

그룹이 얼마나 멀리까지 확장되는지 모호한 경우 정규식 엔진은 가장 긴 일치 항목을 먼저 선호합니다. 모든 파일 이름에 대해 \(.*\)전체 이름과 일치하고 \.*.*빈 문자열과 일치합니다.

확장이 있거나 없는 두 가지 경우가 필요합니다. 또한 파일 이름이 로 시작하는 경우 .이는 확장명의 시작이 아닙니다.

왜 사용하려는지 이해가 되지 않습니다 expr. 쉘 매개변수 조작이 더 쉽습니다.

대문자로 변환할 때 trLinux에서의 구현은 비ASCII 로케일을 지원하지 않습니다. 바이트 조작만 수행합니다. 예를 들어 echo accentué | tr a-z A-Z결과 ACCENTUé는 가 아니라 입니다 ACCENTUÉ. 대신 awk와 같은 로케일 인식 도구를 사용하십시오. Bash에서는 를 사용할 수 있지만 ${filename^^?}sh에서는 사용할 수 없습니다. 스크립트가 파일 이름 인코딩에 맞는 올바른 로캘에서 실행되고 있는지 확인하세요.

파일 이름에 디렉토리 부분이 포함되어 있지 않다고 가정합니다. 그렇다면 먼저 분리하세요.

case $filename in
  ?*.*) # There is an extension
    base="${filename%.*}"; ext=".${filename##*.}";;
  *) # No extension
    base="$filename"; ext="";;
esac
upcased_base="$(printf %s. %base | awk '$0 = toupper($0)')"
upcased="${upcased_base%.}$ext"

그 후행이 .제거 %s.되면 $upcased_base스크립트가 확장명 바로 앞에 개행 문자가 있는 파일 이름을 올바르게 처리하도록 보장합니다. 이것이 없으면 명령 대체로 인해 후행 개행 문자가 제거됩니다. 파일 이름에 개행 문자가 포함되지 않은 것을 이미 확인한 경우에는 이것이 필요하지 않습니다.

답변3

다음은 awk쉘 스크립트에 다음 줄을 입력하는 완전히 기반 솔루션입니다.

uppercasename="$(echo "$filename" | awk 'BEGIN{FS=OFS="."} NF==1{$1=toupper($1)} {for (i=1;i<NF;i++) $i=toupper($i)} 1')"

.필드 구분 기호로 사용됩니다.입력과 출력을 위해필드가 하나만 발견되면 해당 필드를 대문자로 변환하고, 다른 모든 경우에는 마지막 필드를 제외한 모든 필드를 대문자로 변환합니다. 그런 다음 결과를 인쇄합니다(이것은 1의 약어 표기법인 의 의미입니다 {print}).

을 사용하는 경우 bash파이프를 제거하고 다음과 같이 지정할 수 있습니다.

uppercasename="$(awk 'BEGIN{FS=OFS="."} NF==1{$1=toupper($1)} {for (i=1;i<NF;i++) $i=toupper($i)} 1' <<< "$filename")"

here-string을 사용합니다.

.이는 에서와 같이 a로 끝나는 파일 이름의 경계선의 경우 myfile.this.txt.이를 "비어 있지만 존재하는 접미사"처럼 처리하고 로 변환하도록 설계되었습니다 MYFILE.THIS.TXT.. 또한 파일 이름이시작하다a가 있고 .다른 확장자가 없으면( 에서와 같이 .myfile) 소문자로 유지됩니다.

관련 정보