sed를 사용하여 파일 이름 만 얻는 방법


17

sed를 사용하여 파일 이름 만 얻으려면 어떻게해야합니까? 나는 이것을

out_file=$(echo $in_file|sed "s/\(.*\.\).*/\1mp4/g")

그러나 나는 길도 얻었고 /root/video.mp4, 나는 단지 원한다 video.mp4.

답변:


26

basenameGNU coreutils 에서이 작업을 수행하는 데 도움이 될 수 있습니다.

$ basename /root/video.mp4
video.mp4

파일의 확장자를 이미 알고 있다면, 파일 을 제거하기 위해 basename구문 basename NAME [SUFFIX]을 사용하여 호출 할 수 있습니다 .

$ basename /root/video.mp4 .mp4
video

또는 다른 옵션은 다음을 사용하여 마지막 점 이후의 모든 것을 자르는 것입니다 sed.

$ basename /root/video.old.mp4 | sed 's/\.[^.]*$//'
video.old

3
사용 sed 's/\.[^.]*$//'당신이 가지고, (숨겨진)에 대한 실패 .filename...디렉토리
Peter.O

9

가장 쉬운 해결책은 /다음 과 같이 마지막에 나타날 때까지 모든 것을 제거하는 것입니다 .

echo /root/video.mp4 | sed 's/.*\///'


5

다음 방법 중 하나를 사용하십시오.

out_file="${in_file##*/}"

out_file="$(basename $in_file)"

out_file="$(echo $in_file | sed 's=.*/==')"

out_file="$(echo $in_file | awk -F"/" '{ print $NF }')"

추신. 명령문 \(.*\.\)에서 처음부터 점 ( /root/video.) 까지 문자열과 일치 하므로 동일한 문자열 을 얻은 다음 .mp4원래 문자열과 동일한 문자열 을 수동으로 추가 합니다. s=.*\([^/]*\)=\1=대신 사용해야 합니다.

업데이트 : (첫 번째는 지금 수정되었습니다)

확장자가없는 유일한 파일 이름을 얻으려면 다음을 수행하십시오.

out_file="$(echo $in_file | sed 's=.*/==;s/\.[^.]*$/.new_ext/')"

out_file="$(echo $in_file | sed 's=\([^/]*\)\.[^./]*$=\1.new_ext=')"

out_file="$(echo $in_file | awk -F"/" '{ gsub (/\.[^/.]*$/,".new_ext",$NF);print $NF }'

그러나 이러한 방법 중 하나를 사용하면 형식이있는 파일 이름이 표시되고 파일 이름 만 가져 와서 새 형식을 수동으로 입력해야합니다.
Shixons

아, 말이 되네요. 내 답변을 업데이트했습니다.
돌진

@rush : 예를 들어 파일 이름과 같은 경우가 있습니다 my.file.tar.gz.
donothingsuccessfully

@donothingssuccessfully 마지막에 sed및 누락 된 점 기호가있었습니다 awk. 결정된. 감사합니다.
돌진

4

정규식을 사용하는 기본 요소 중 하나는 와일드 카드를 지정할 때 패턴이 본질적으로 욕심이다는 것입니다. @uloBasEI가 제안한 답변은 확실한 답변이지만 basename 명령을 사용해야합니다. @Shixons의 원래 질문은 sed 만 사용하여 솔루션을 요청합니다.

계속하기 전에, 어느 버전의 sed가 대상인지 아는 것이 항상 도움이됩니다. BSD를 가정하고 있습니다 (OSX와 함께 제공됨).

우선, 원래 질문에서 제안 된 패턴은 입력 문자열의 시작부터 마지막 ​​점까지의 모든 것을 캡처하기 때문에 작동하지 않습니다. 앵커가 없으면이 검색은 모든 것을 왼쪽에서 오른쪽으로 삼 킵니다. 따라서 "/ 1"일치 패턴은 마지막 점까지 모든 것을 포함합니다. 여러 개의 점이있는 파일 이름도 전체적으로 삼켜집니다. 원하는 결과가 아닙니다.

첫 번째 단계는 패턴을 식별하기위한 전략을 수립하는 것입니다. 여기에서 파일 이름 왼쪽에있는 모든 것을 제거하고 싶습니다 (나중에 확장명을 다룰 것입니다).

out_file="$(echo $in_file | sed 's/^\(\/.*\/\)*.*/\1/')"

문자열의 처음부터 검색이 일치합니다. "/.*"패턴을 0 번 이상 일치시키고 나중에 모든 것을 삭제합니다. 일치하는 패턴을 "\ 1"로 인쇄합니다. 우리는 전 세계적으로 검색하지 않습니다. ^ 앵커를 지정하여 문자열의 처음부터 검색합니다.

"-E"옵션을 활성화하여 명확성을 높이면 괄호를 피할 필요가 없습니다.

out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*.*/\1/')"

이제 왼쪽에 부분이 있습니다. 오른쪽 부분을 추가합시다. 왼쪽 부분을 패턴으로 유지해야하므로 0 번 이상 나타나도록 지정할 수 있습니다. 우리가 지금하는 일은 오른쪽 부분에 패턴을 추가하는 것입니다.

out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*(.*)/\2/')"

두 번째 일치 항목 만 인쇄하여 파일 이름 이외의 모든 것을 버립니다. 그러나 여전히 파일 이름 확장자를 제거해야합니다.

out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*(.*)\..*$/\2/')"

끝에있는 "$"는 선택 사항입니다.

마지막으로 새 확장을 추가하려면 다음과 같이 수정하십시오.

out_file="$(echo $in_file | sed -E 's/^(\/.*\/)*(.*)\..*$/\2.mp4/')"

추가 최적화는 상대 경로를 처리하기 위해 첫 번째 슬래시를 선택적으로 만드는 것입니다.

out_file="$(echo $in_file | sed -E 's/^([\/]?.*\/)*(.*)\..*$/\2.mp4/')"

나는 basename 을 대체 할 sed 패턴을 찾는 동안 게 으르 면서이 질문을 보았습니다 . 해당 명령이 설치되지 않은 벗겨진 시스템에서 작업하고 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.