bash의 경로 문자열에서 파일 접미사와 경로 부분을 어떻게 제거합니까?
문제
다음과 같은 문자열 파일 경로가 주어졌습니다 /foo/fizzbuzz.bar
, Bash를 사용하여 어떻게 추출합니까? fizzbuzz
상기 문자열의 일부?
해결책
Bash의 # 및 % 연산자와 함께 수행하는 방법은 다음과 같습니다.
$ x="/foo/fizzbuzz.bar"
$ y=${x%.bar}
$ echo ${y##*/}
fizzbuzz
${x%.bar}
또한 가능합니다 ${x%.*}
도트 또는 다음에 모든 것을 제거합니다 ${x%%.*}
첫 번째 점 후 모든 것을 제거합니다.
예시:
$ x="/foo/fizzbuzz.bar.quux"
$ y=${x%.*}
$ echo $y
/foo/fizzbuzz.bar
$ y=${x%%.*}
$ echo $y
/foo/fizzbuzz
문서는 다음에 있습니다 강타 매뉴얼. 찾다 ${parameter%word}
그리고 ${parameter%%word}
후행 부분 일치 섹션.
다른 팁
Basename 명령을보십시오.
NAME=$(basename /foo/fizzbuzz.bar .bar)
순수한 배쉬, 두 개의 별도 작업에서 수행됩니다.
경로 스트링에서 경로를 제거하십시오.
path=/foo/bar/bim/baz/file.gif file=${path##*/} #$file is now 'file.gif'
경로 스트링에서 확장을 제거하십시오.
base=${file%.*} #${base} is now 'file'.
Basename을 사용하여 다음을 사용하여이를 달성했습니다.
for file in *; do
ext=${file##*.}
fname=`basename $file $ext`
# Do things with $fname
done;
이를 통해 파일 확장에 대한 사전 지식이 필요하지 않으며 파일 이름에 도트가있는 파일 이름이있는 경우에도 작동합니다 (확장자 앞에서). 프로그램이 필요합니다 basename
그러나 이것은 GNU Coreutils의 일부이므로 모든 배포판으로 배송해야합니다.
순수한 배쉬 웨이 :
~$ x="/foo/bar/fizzbuzz.bar.quux.zoom";
~$ y=${x/\/*\//};
~$ echo ${y/.*/};
fizzbuzz
이 기능은 "매개 변수 확장"하에서 MAN BASH에 대해 설명합니다. 비 강타 방법 : awk, perl, sed 등.
편집 : 파일의 점과 함께 작동합니다 접미사 접미사 (확장)를 알 필요는 없지만 그렇지 않습니다 도트로 작업하십시오 이름 그 자체.
Basename 및 Dirname 함수는 다음과 같습니다.
mystring=/foo/fizzbuzz.bar
echo basename: $(basename "${mystring}")
echo basename + remove .bar: $(basename "${mystring}" .bar)
echo dirname: $(dirname "${mystring}")
출력이 있습니다 :
basename: fizzbuzz.bar
basename + remove .bar: fizzbuzz
dirname: /foo
perl -pe 's/\..*$//;s{^.*/}{}'
사용 basename
파일 확장자가 무엇인지 알고 있다고 가정하지 않습니까?
그리고 나는 다양한 정규 표현 제안이 하나 이상의 ""프라이나 이름에 대처하지 않는다고 생각합니다.
다음은 이중 점에 대처하는 것 같습니다. 오, 그리고 "/"자신 (킥을 위해)을 포함하는 파일 이름
Pascal을 역설적으로 말하면, "이 대본은 너무 길다. 나는 그것을 더 짧게 만들 시간이 없었다"고 말했다.
#!/usr/bin/perl
$fullname = $ARGV[0];
($path,$name) = $fullname =~ /^(.*[^\\]\/)*(.*)$/;
($basename,$extension) = $name =~ /^(.*)(\.[^.]*)$/;
print $basename . "\n";
다른 게시물에서 제안 된대로 Basename을 사용할 수없는 경우 언제든지 SED를 사용할 수 있습니다. 다음은 (못생긴) 예입니다. 가장 크지는 않지만 원하는 문자열을 추출하고 입력을 원하는 문자열로 대체하여 작동합니다.
echo '/foo/fizzbuzz.bar' | sed 's|.*\/\([^\.]*\)\(\..*\)$|\1|g'
출력을 얻을 수 있습니다
fizzbuzz
여기에 덧붙여 POSIX Conformant Syntax 사용 이 답변,
basename 끈 [접미사]
에서와 같이
basename /foo/fizzbuzz.bar .bar
암소 비슷한 일종의 영양 basename
다른 구문을 지원합니다.
basename -s .bar /foo/fizzbuzz.bar
같은 결과로. 차이점과 장점은 -s
암시합니다 -a
, 여러 인수를 뒷받침하는 :
$ basename -s .bar /foo/fizzbuzz.bar /baz/foobar.bar
fizzbuzz
foobar
이것은 또한 -z
예를 들어 공백, Newlines 및 Glob 캐릭터가 포함 된 이러한 파일에 대한 옵션 ( ls
):
$ ls has*
'has'$'\n''newline.bar' 'has space.bar' 'has*.bar'
배열로 읽기 :
$ readarray -d $'\0' arr < <(basename -zs .bar has*)
$ declare -p arr
declare -a arr=([0]=$'has\nnewline' [1]="has space" [2]="has*")
readarray -d
Bash 4.4 또는 새로 필요한 것이 필요합니다. 이전 버전의 경우 다음을 고려해야합니다.
while IFS= read -r -d '' fname; do arr+=("$fname"); done < <(basename -zs .bar has*)
제안 된 Perl 솔루션을 조심하십시오 : 첫 번째 점 후에는 아무것도 제거합니다.
$ echo some.file.with.dots | perl -pe 's/\..*$//;s{^.*/}{}'
some
Perl과 함께하고 싶다면 이것이 효과가 있습니다.
$ echo some.file.with.dots | perl -pe 's/(.*)\..*$/$1/;s{^.*/}{}'
some.file.with
그러나 Bash를 사용하는 경우 솔루션 y=${x%.*}
(또는 basename "$x" .ext
확장을 알고 있다면)는 훨씬 간단합니다.
Basename은 그렇게하고 경로를 제거합니다. 주어진 경우 접미사를 제거하고 파일의 접미사와 일치하지만 명령에 제공하려면 접미사를 알아야합니다. 그렇지 않으면 MV를 사용하고 새 이름이 다른 방법을 알아낼 수 있습니다.
최고 등급의 답변을 2 위 등급 답변과 결합하여 전체 경로없이 파일 이름을 얻습니다.
$ x="/foo/fizzbuzz.bar.quux"
$ y=(`basename ${x%%.*}`)
$ echo $y
fizzbuzz