셸 스크립트에서 파일 이름 확장자를 제거하려면 어떻게 해야 합니까?
다음 코드에 무슨 문제가 있습니까?
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 '.')
코드 설명:
echo
옵 가 져 니 니 다$filename
합니다.- 그런 다음 출력물을 가져와 파이프로 연결합니다.
cut
- 그
cut
기호함로합니다.-f
합니다. - 에 그면러그.
$()
을 가져오고 합니다. - 인 반된값이지변할수다니당됩에정된름은에 됩니다.
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)
코드에 두 가지 문제가 있습니다.
- 변수에 저장할 문자열을 생성하는 명령을 둘러싸려면 "(뒤쪽 눈금) 대신 "(체크 표시)를 사용했습니다.
- 파이프에 대한 변수 "$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
'programing' 카테고리의 다른 글
Laravel에서 만료된 토큰 처리 중 (0) | 2023.08.17 |
---|---|
마우스가 끝나면 버튼 색상 변경 (0) | 2023.05.29 |
MongoDB 집계:고유 필드 카운트 (0) | 2023.05.29 |
번들에서 'Main'이라는 이름의 스토리보드를 찾을 수 없습니다. (0) | 2023.05.29 |
CSS 부모 선택기가 있습니까? (0) | 2023.05.29 |