bash의 경로 문자열에서 파일 접미사와 경로 부분을 어떻게 제거합니까?

StackOverflow https://stackoverflow.com/questions/125281

  •  02-07-2019
  •  | 
  •  

문제

다음과 같은 문자열 파일 경로가 주어졌습니다 /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)

순수한 배쉬, 두 개의 별도 작업에서 수행됩니다.

  1. 경로 스트링에서 경로를 제거하십시오.

    path=/foo/bar/bim/baz/file.gif
    
    file=${path##*/}  
    #$file is now 'file.gif'
    
  2. 경로 스트링에서 확장을 제거하십시오.

    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
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top