Programming

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

procodes 2020. 2. 28. 19:38
반응형

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


과 같은 문자열 파일 경로가 주어지면 /foo/fizzbuzz.barbash를 사용하여 해당 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

설명서는 Bash 매뉴얼 에서 찾을 수 있습니다 . 찾으 ${parameter%word}${parameter%%word}부 정합 부 후단.


basename 명령을보십시오 :

NAME=$(basename /foo/fizzbuzz.bar .bar)

두 가지 별도 작업으로 수행되는 순수 bash :

  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에서 "Parameter Expansion"에 설명되어 있습니다. 비 배쉬 방법은 풍부합니다 : 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{^.*/}{}'

Using basename는 파일 확장자가 무엇인지 알고 있다고 가정합니까?

그리고 다양한 정규식 제안이 하나 이상의 ""를 포함하는 파일 이름에 대처하지 못한다고 생각합니다.

다음은 이중 점에 대처하는 것 같습니다. 아, "/"자체를 포함하는 파일 이름 (킥만)

파스칼의 말을 인용하자면, "이 스크립트는 너무 깁니다. 더 짧게 만들 시간이 없었습니다."


  #!/usr/bin/perl
  $fullname = $ARGV[0];
  ($path,$name) = $fullname =~ /^(.*[^\\]\/)*(.*)$/;
  ($basename,$extension) = $name =~ /^(.*)(\.[^.]*)$/;
  print $basename . "\n";
 

다른 게시물에서 제안한대로 기본 이름을 사용할 수없는 경우 언제든지 sed를 사용할 수 있습니다. 다음은 (못생긴) 예입니다. 가장 크지는 않지만 원하는 문자열을 추출하고 입력을 원하는 문자열로 대체하여 작동합니다.

echo '/foo/fizzbuzz.bar' | sed 's|.*\/\([^\.]*\)\(\..*\)$|\1|g'

어떤 결과를 얻을 수 있습니까?

피즈 버즈


또한받는 POSIX 준수 구문 에서 사용 이 응답 ,

basename string [suffix]

에서와 같이

basename /foo/fizzbuzz.bar .bar

GNUbasename 는 다른 구문을 지원합니다.

basename -s .bar /foo/fizzbuzz.bar

같은 결과로. 차이점과 장점은 여러 인수를 지원 하는 -simplies입니다 -a.

$ basename -s .bar /foo/fizzbuzz.bar /baz/foobar.bar
fizzbuzz
foobar

-z옵션 옵션을 사용하여 출력을 NUL 바이트로 분리하여 파일 이름을 안전하게 만들 수도 있습니다 ( 예 : 공백, 개행 및 글로브 문자가 포함 된 파일의 경우 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 -dBash 4.4 이상이 필요합니다. 이전 버전의 경우 다음을 반복해야합니다.

while IFS= read -r -d '' fname; do arr+=("$fname"); done < <(basename -zs .bar has*)

제안 된 펄 솔루션에주의하십시오 : 첫 번째 점 뒤의 모든 것을 제거합니다.

$ echo some.file.with.dots | perl -pe 's/\..*$//;s{^.*/}{}'
some

펄로하고 싶다면 다음과 같이하십시오.

$ echo some.file.with.dots | perl -pe 's/(.*)\..*$/$1/;s{^.*/}{}'
some.file.with

하지만 당신은 강타와 솔루션을 사용하는 경우 y=${x%.*}(또는 basename "$x" .ext당신이 확장을 알고있는 경우에) 훨씬 더 간단합니다.


기본 이름으로 경로를 제거합니다. 제공된 접미사와 파일의 접미사와 일치하는 경우 접미사도 제거하지만 명령에 제공 할 접미사를 알아야합니다. 그렇지 않으면 mv를 사용하여 다른 이름이 무엇인지 알아낼 수 있습니다.


전체 경로없이 파일 이름을 얻으려면 최상위 답변과 두 번째 최상위 답변을 결합하십시오.

$ x="/foo/fizzbuzz.bar.quux"
$ y=(`basename ${x%%.*}`)
$ echo $y
fizzbuzz

참고 : https://stackoverflow.com/questions/125281/how-do-i-remove-the-file-suffix-and-path-portion-from-a-path-string-in-bash



반응형