programing

셸 스크립트에서 파일 이름 확장자를 제거하려면 어떻게 해야 합니까?

javaba 2023. 5. 29. 21:48
반응형

셸 스크립트에서 파일 이름 확장자를 제거하려면 어떻게 해야 합니까?

다음 코드에 무슨 문제가 있습니까?

name='$filename | cut -f1 -d'.''

그대로, 나는 문자 그대로의 문자열을 얻습니다.$filename | cut -f1 -d'.'인용문을 삭제해도 아무 것도 얻지 못합니다.한편,, 타핑을 합니다.

"test.exe" | cut -f1 -d'.'

쉘 안에서 내가 원하는 결과물을 얻을 수 있습니다.test는 이미 알고 있습니다.$filename올바른 값이 할당되었습니다.제가 하고 싶은 것은 확장자가 없는 파일 이름을 변수에 할당하는 것입니다.

매개 변수 확장을 사용할 수도 있습니다.

$ filename=foo.txt
$ echo "${filename%.*}"
foo

파일 이름뿐만 아니라 파일 경로가 있는 경우basename확장자를 포함한 파일 이름만 가져옵니다.( 않경점예만이있경로는우에면으그렇지예경(우▁only▁there:있는▁otherwise▁dot▁if▁(e:path.to/myfile또는./myfile경로에 점이 없더라도 경로 내에서 트리밍됩니다. (예를 들어, 경로에 점이 없는 경우).path/to/myfile가 이길그렇면다면인 path/to/myfile.txt):

$ filepath=path.to/foo.txt
$ echo "${filepath%.*}"
path.to/foo
$ filename=$(basename $filepath)
$ echo $filename
foo.txt
$ echo "${filename%.*}"
foo

파이이점으시예만작경는우하로름일예경우(▁(▁just:▁the는▁dot하작시▁only▁if:.bashrc전체 파일 이름이 제거됩니다.

확장명을 알고 있는 경우 기본 이름을 사용할 수 있습니다.

$ basename /home/jsmith/base.wiki .wiki
base

명령 대체 구문을 사용해야 합니다.$(command)스크립트/명령에서 명령을 실행하려는 경우.

그래서 당신의 대사는

name=$(echo "$filename" | cut -f 1 -d '.')

코드 설명:

  1. echo 옵 가 져 니 니 다$filename합니다.
  2. 그런 다음 출력물을 가져와 파이프로 연결합니다.cut
  3. cut 기호함로합니다.-f합니다.
  4. 에 그면러그.$()을 가져오고 합니다.
  5. 인 반된값이지변할수다니당됩에정된름은에 됩니다.name

첫 의 일부를 수 있습니다..:

$ filename=hello.world
$ echo "$filename" | cut -f 1 -d '.'
hello
$ filename=hello.hello.hello
$ echo "$filename" | cut -f 1 -d '.'
hello
$ filename=hello
$ echo "$filename" | cut -f 1 -d '.'
hello

파일 이름에 확장명의 점이 아닌 점이 포함된 경우 다음을 사용합니다.

echo $filename | rev | cut -f 2- -d '.' | rev

POSIX의 기본 제공 기능만 사용:

#!/usr/bin/env sh
path=this.path/with.dots/in.path.name/filename.tar.gz

# Get the basedir without external command
# by stripping out shortest trailing match of / followed by anything
dirname=${path%/*}

# Get the basename without external command
# by stripping out longest leading match of anything followed by /
basename=${path##*/}

# Strip uptmost trailing extension only
# by stripping out shortest trailing match of dot followed by anything
oneextless=${basename%.*}; echo "$oneextless" 

# Strip all extensions
# by stripping out longest trailing match of dot followed by anything
noext=${basename%%.*}; echo "$noext"

# Printout demo
printf %s\\n "$path" "$dirname" "$basename" "$oneextless" "$noext"

데모 인쇄:

this.path/with.dots/in.path.name/filename.tar.gz
this.path/with.dots/in.path.name
filename.tar.gz
filename.tar
filename
file1=/tmp/main.one.two.sh
t=$(basename "$file1")                        # output is main.one.two.sh
name=$(echo "$file1" | sed -e 's/\.[^.]*$//') # output is /tmp/main.one.two
name=$(echo "$t" | sed -e 's/\.[^.]*$//')     # output is main.one.two

아무거나 마음대로 쓰세요.여기서 나는 그것이 마지막이라고 가정합니다..(점) 다음에 확장자 텍스트가 나옵니다.

#!/bin/bash
file=/tmp/foo.bar.gz
echo $file ${file%.*}

출력:

/tmp/foo.bar.gz /tmp/foo.bar

마지막 확장자만 제거됩니다.

Zsh 단위:

fullname=bridge.zip
echo ${fullname:r}

간단하고 깨끗하며 체인으로 연결하여 둘 이상의 확장을 제거할 수 있습니다.

fullname=bridge.tar.gz
echo ${fullname:r:r}

그리고 그것은 다른 유사한 수식어들과 결합될 수 있습니다.

를 사용하는 것이 좋습니다.basename.
Ubuntu에서는 기본적으로 시각적으로 단순한 코드이며 대부분의 경우를 처리합니다.

다음은 공백 및 다중 점/하위 확장을 처리하는 몇 가지 하위 사례입니다.

pathfile="../space fld/space -file.tar.gz"
echo ${pathfile//+(*\/|.*)}

그것은 보통 처음부터 연장을 제거합니다..하지만 우리는 실패합니다...경로.

echo **"$(basename "${pathfile%.*}")"**  
space -file.tar     # I believe we needed exatly that

여기 중요한 참고 사항이 있습니다.

공백을 처리하기 위해 큰따옴표 안에 큰따옴표를 사용했습니다.$를 문자로 보내기 때문에 단일 견적은 통과되지 않습니다.Bash는 비정상적이며 확장으로 인해 "두 번째 "첫 번째" 인용문"을 읽습니다.

하지만, 당신은 여전히 생각할 필요가 있습니다..hidden_files

hidden="~/.bashrc"
echo "$(basename "${hidden%.*}")"  # will produce "~" !!!  

예상한 "" 결과가 아닙니다.실행을 위해 사용$HOME또는/home/user_path/
왜냐하면 bash는 "비정상적"이고 "~"을 확장하지 않기 때문입니다(bashPitfalls 검색).

hidden2="$HOME/.bashrc" ;  echo '$(basename "${pathfile%.*}")'
#!/bin/bash
filename=program.c
name=$(basename "$filename" .c)
echo "$name"

출력:

program

이전에 제공된 답변에 점이 포함된 경로에 문제가 있습니다.몇 가지 예:

/xyz.dir/file.ext
./file.ext
/a.b.c/x.ddd.txt

사용하는 것을 선호합니다.|sed -e 's/\.[^./]*$//'예:

$ echo "/xyz.dir/file.ext" | sed -e 's/\.[^./]*$//'
/xyz.dir/file
$ echo "./file.ext" | sed -e 's/\.[^./]*$//'
./file
$ echo "/a.b.c/x.ddd.txt" | sed -e 's/\.[^./]*$//'
/a.b.c/x.ddd

참고: 여러 확장자를 제거하려면(마지막 예와 같이) 다음을 사용합니다.|sed -e 's/\.[^/]*$//':

$ echo "/a.b.c/x.ddd.txt" | sed -e 's/\.[^/]*$//'
/a.b.c/x

그러나 확장자가 없는 "dot-files"에서는 이 방법이 실패합니다.

$ echo "/a.b.c/.profile" | sed -e 's/\.[^./]*$//'
/a.b.c/

이러한 경우에도 적용할 수 있습니다.

$ echo "/a.b.c/.profile" | sed -re 's/(^.*[^/])\.[^./]*$/\1/'
/a.b.c/.profile

이것은 모든 가능성을 다룹니다! (경로에 점이 있든 없든, 확장자가 있든 없든):

tmp1=${filename##*/};tmp2=${tmp1:1};filename_noextension=$(echo -n ${tmp1:0:1};echo ${tmp2%.*});echo $filename_noextension

주의:

  • 확장자 없이 파일 이름을 제공합니다.그래서 그 안에 길이 없습니다.$filename_noextension변수.
  • 두 개의 원치 않는 변수가 발생합니다.$tmp1그리고.$tmp2스크립트에서 사용하지 않는지 확인합니다.

테스트할 예:

filename=.bashrc; echo "filename: $filename"; tmp1=${filename##*/};tmp2=${tmp1:1};filename_noextension=$(echo -n ${tmp1:0:1};echo ${tmp2%.*}); echo "filename without extension: $filename_noextension"

filename=.bashrc.txt; echo "filename: $filename"; tmp1=${filename##*/};tmp2=${tmp1:1};filename_noextension=$(echo -n ${tmp1:0:1};echo ${tmp2%.*}); echo "filename without extension: $filename_noextension"

filename=.bashrc.txt.tar; echo "filename: $filename"; tmp1=${filename##*/};tmp2=${tmp1:1};filename_noextension=$(echo -n ${tmp1:0:1};echo ${tmp2%.*}); echo "filename without extension: $filename_noextension"

filename=~/.bashrc; echo "filename: $filename"; tmp1=${filename##*/};tmp2=${tmp1:1};filename_noextension=$(echo -n ${tmp1:0:1};echo ${tmp2%.*}); echo "filename without extension: $filename_noextension"

filename=~/.bashrc.txt.tar; echo "filename: $filename"; tmp1=${filename##*/};tmp2=${tmp1:1};filename_noextension=$(echo -n ${tmp1:0:1};echo ${tmp2%.*}); echo "filename without extension: $filename_noextension"

filename=bashrc; echo "filename: $filename"; tmp1=${filename##*/};tmp2=${tmp1:1};filename_noextension=$(echo -n ${tmp1:0:1};echo ${tmp2%.*}); echo "filename without extension: $filename_noextension"

filename=bashrc.txt; echo "filename: $filename"; tmp1=${filename##*/};tmp2=${tmp1:1};filename_noextension=$(echo -n ${tmp1:0:1};echo ${tmp2%.*}); echo "filename without extension: $filename_noextension"

filename=bashrc.txt.tar; echo "filename: $filename"; tmp1=${filename##*/};tmp2=${tmp1:1};filename_noextension=$(echo -n ${tmp1:0:1};echo ${tmp2%.*}); echo "filename without extension: $filename_noextension"

filename=~/bashrc; echo "filename: $filename"; tmp1=${filename##*/};tmp2=${tmp1:1};filename_noextension=$(echo -n ${tmp1:0:1};echo ${tmp2%.*}); echo "filename without extension: $filename_noextension"

filename=~/bashrc.txt.tar; echo "filename: $filename"; tmp1=${filename##*/};tmp2=${tmp1:1};filename_noextension=$(echo -n ${tmp1:0:1};echo ${tmp2%.*}); echo "filename without extension: $filename_noextension"

Hawker65가 셰프너 답변의 코멘트에서 지적했듯이, 가장 많이 투표된 솔루션은 다중 확장자(filename.tar.gz 등)나 나머지 경로의 점(이 .path/with.dll/in.path.name 등)을 처리하지 않습니다.가능한 해결책은 다음과 같습니다.

a=this.path/with.dots/in.path.name/filename.tar.gz
echo $(dirname $a)/$(basename $a | cut -d. -f1)

코드에 두 가지 문제가 있습니다.

  1. 변수에 저장할 문자열을 생성하는 명령을 둘러싸려면 "(뒤쪽 눈금) 대신 "(체크 표시)를 사용했습니다.
  2. 파이프에 대한 변수 "$filename"을 "cut" 명령으로 "echo"하지 않았습니다.

아래와 같이 코드를 "name='filename $delay | cut -f 1 -d'."로 변경합니다(다시 한 번, 이름 변수 정의를 둘러싼 뒤 눈금).

$> filename=foo.txt
$> echo $filename
foo.txt
$> name=`echo $filename | cut -f1 -d'.'`
$> echo $name
foo
$> 

편집: 답변에 추가할 수 있다면 백 틱 대신 $(...) 구조를 사용할 것입니다.저는 그것이 훨씬 더 깨끗하고, 틱 혼란이 덜하다고 생각합니다.

도트 파일에서 작동하지 않는 여러 솔루션을 사용해 본 결과, Bash와 호환되는 고급 솔루션이 있습니다.

# Given a file path, return only the file name, stripped of its extension.
basefilename()
{
    filename="$(basename "$1")"
    prefix=

    if [[ ${filename::1} == . ]]; then
        prefix=.
        filename="${filename:1}"
    fi

    echo -n "$prefix"
    echo "$filename" | rev | cut -f 2- -d '.' | rev
}

하지만 저는 몇 가지 경우에만 테스트를 했습니다.개선 사항이 있으면 저에게 알려주세요.

여기에 이미지 설명 입력

파일 확장명이 .new라고 가정합니다.

ls -1 | awk '{ print "mv "$1" `basename "$1" .new`"}' | sh

게시 후 특별한 견적이 나오지 않으므로 이미지를 참조하시기 바랍니다.

언급URL : https://stackoverflow.com/questions/12152626/how-can-i-remove-the-extension-of-a-filename-in-a-shell-script

반응형