확장자를 제외한 파일 이름의 점을 밑줄로 대체


9

누군가 파일 이름을 바꾸는 방법에 대해 제안 할 수 있습니까?

head.body.date.txt

에:

head_body_date.txt

Unix 에서 이름 바꾸기를 수행하는 단일 행 명령문이 있습니까?


9
그것이 .tar.gz확장 이라고 가정 합니까? 또한 U & L에 오신 것을 환영합니다!
EKons

2
당신은 정말로 리눅스가 아니라 유닉스를 의미합니까? 어떤 유닉스?
terdon

1
확실한 대답은 mv head.body.date.txt head_body_date.txt입니다. 다른 제한 사항이나 실제 예가있는 경우 질문을 다음과 같이 업데이트하십시오. 현재로서는 질문이 명시 적 이름을 가진 파일, 모든 파일이 특정 형식을 갖는 단일 디렉토리인지 또는 특정 이름에 대한 디렉토리 계층 구조를 검색하여 변경 하려는지 확실하지 않습니다.
Kusalananda

답변:


9

파일 이름을 반복하고 변환을 위해 매개 변수 확장을 사용하십시오.

for f in *.*.*.txt; do i="${f%.txt}"; echo mv -i -- "$f" "${i//./_}.txt"; done

매개 변수 확장 패턴 은 파일 이름 ( ) 에서 ${f//./_}모든을 .s로 바꿉니다 ._$f

위는 드라이 런을 수행하여 실제 이름을 바꾸려면 제거하십시오 echo.

for f in *.*.*.txt; do i="${f%.txt}"; mv -i -- "$f" "${i//./_}.txt"; done

확장 기능을 다루고 싶다면 .txt:

for f in *.*.*.*; do pre="${f%.*}"; suf="${f##*.}"; \
                     echo mv -i -- "$f" "${pre//./_}.${suf}"; done

echo실제 조치 제거 를 확인한 후 :

for f in *.*.*.*; do pre="${f%.*}"; suf="${f##*.}"; \
                     mv -i -- "$f" "${pre//./_}.${suf}"; done

임의의 수의 점에 대해 일반 : 하나 이상 :

for f in *.*; do pre="${f%.*}"; suf="${f##*.}"; \
                 mv -i -- "$f" "${pre//./_}.${suf}"; done

임의의 수의 점이 있으면 일반적인 방법이 있습니까?
Ciprian Tomoiagă

1
@CiprianTomoiaga Do :for f in *.*; do ...; done
heemayl

*.*코드가 고정 된 수의 점에서만 작동하는 것처럼 보이기 때문에 예제에서 패턴을 똑바로 배치하는 것이 좋습니다 .
ilkkachu

@ilkkachu 공정, 충분히 편집했습니다.
heemayl

너무나 감사합니다, 그것은 나를 위해 일했습니다. 그리고 약간의 학습!
SG

4

perl기반rename

$ rename -n 's/\.[^.]+$(*SKIP)(*F)|\./_/g' head.body.date.txt 
rename(head.body.date.txt, head_body_date.txt)
  • \.[^.]+$(*SKIP)(*F) 이 패턴을 건너 뛰고 대체 일치 항목을 찾으십시오.
  • |\./_/g모두 .로 바꾸다_

또는 부정적 예측을 사용

$ rename -n 's/\.(?![^.]+$)/_/g' head.body.date.txt 
rename(head.body.date.txt, head_body_date.txt)

괜찮 으면 -n옵션을 제거하십시오.


3
rename 's/\.(?=[^.]*\.)/_/g' *.txt

정규식 대체를 사용 .하여 파일 이름에서 마지막 인스턴스를 제외한 모든 인스턴스를 찾고 (캡처하지 않는 미리보기)이를 대체합니다 _. *.*원하는 경우 일반화합니다 .

(이 특정 버전 rename은를 통해 설치되는 것으로 보입니다 util-linux). 나는 사용하고 있습니다 Ubuntu 12.04(예, 심각하게 오래된 기계).


2

bash:

old=head.body.date.txt oldb=${old%.*} olde=${old##*.} ; \
mv -- "$old" "${oldb//./_}.${olde}"

(1)로 mv --시작하는 "오래된"파일 이름으로부터 보호하기 위해을 사용해야 합니다 -. (2) 셸에 특수한 공백이나 문자가 포함 된 "이전"파일 이름 (예 : 및 ) 을 막기 위해 $old따옴표 ( "$old")를 입력해야합니다 . (3) 확장에 밑줄이 포함 된 다소 병리학 적 경우 답변이 실패 합니다 . *?head.body.date.t_xthead_body_date_t.xt
Scott

@ 스콧, 감사합니다. 코드는 이제 언급 된 세 항목 모두에 따라 조정됩니다.
agc

1

사용 mv, sed그리고 rev한 줄에 :

mv "head.body.date.txt" "$(echo head.body.date.txt | rev | sed 's/\./_/2g' | rev)"

txt현재 담당자의 모든 파일에 파일 을 적용하려면 mv작동 방식으로 인해 globs를 사용하는 것이 까다로워 보이지만 for단일 라이너에서 루프를 수행 할 수 있습니다 .

for file in *.txt; do mv "$file" "$(echo $file | rev | sed 's/\./_/2g' | rev)"; done

약간 길지만 루프의 여러 패턴을 일치시킬 수 있습니다!


2
(1) 아르 기! 하지 마라 $(ls …). 그냥하세요 for file in *.txt. (2) 더 많은 따옴표를 사용해야합니다 mv "$file" "$(…)".
Scott

고맙게도 편집하고 편집 한 Scott에게 감사합니다! 나는 아직 껍질을 벗고있는 젊은이이다. 부드럽게 해주세요.)
Valentin B.

지나고 나서 보니, 사용하는 rename몇 가지 다른 이들처럼 자신의 대답에 제안했다 않지만 사운드 간단 ...
발렌틴 B.

-1
 mv head.body.date.txt head_body_date.txt

한 번에 하나의 파일만큼 간단합니다. 디렉토리 내에서 또는 전체 디렉토리로 재귀 적으로 수행할지 여부를 지정하지 않으므로 가장 편리하고 빠른 솔루션입니다.

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