find 명령을 사용하여 파일 이름에서 (1)을 제거하는 방법


13

최근에 Mac OS 10.7 (Lion)에서 XLD를 사용하여 모든 FLAC 파일을 44.1kHz의 낮은 샘플링 속도와 24 비트의 비트 심도로 변환했습니다 (iPhone / iPod는 그 이상을 지원하지 않기 때문에).

XLD에 이전의 모든 파일을 덮어 쓰라고했지만 XLD (1)는 다음과 같이 파일 끝에 끝에 a 를 추가했습니다 .

some_song.m4a

some_song(1).m4a

이제 (1)변환 한 모든 FLAC 파일에서 해당 파일 을 제거하고 싶습니다 .

파일 이름을 바꾸기 위해 일부 프로그램이나 AppleScript를 사용할 수도 있었지만 구식 명령 줄을 사용하여 배우고 싶었습니다.

나는 아는 find . -name *\(1\).m4a모든 변환 FLAC 파일을 잡아 것입니다.

다음으로 나는 찾은 모든 파일로 무언가를 -exec하고 mv이름을 바꿔야한다는 것을 알고 있습니다. 그러나 내가 알아낼 수없는 것은 원래 파일 이름을 유지하고 만 제거하는 방법 (1)입니다.

어쩌면 수정하고 싶지 않은 파일 이름의 일부를 저장하기 위해 그룹 정규식 캡처를 수행해야합니까? 또는 한 줄로 모든 것을 할 수는 없으며 쉘 스크립트를 만들어야합니다.

모든 팁이나 제안을 환영합니다! 감사!


5
왜 공감해야합니까? 그것은 유효한 질문처럼 보입니다 ...

귀하의 특정 질문과 관련이 find없지만 실제 문제를 해결하고 (오디오 파일 변환) audiotools.sourceforge.net 및이 예제 사례 (macosx lion의 경우) invibe.net/을 살펴보십시오. LaurentPerrinet / SciBlog / 2012-04-22
meduz

답변:


13

find최후의 수단을 제외하고 출력 을 구문 분석하지 마십시오 . Unix 파일 시스템에서 파일 이름은 문자열 (일반적인 오해)이 아니라 null 문자를 제외한 모든 문자를 포함 할 수있는 이진 blob 이라는 것을 알아야합니다 /. 파일 이름을 안전하고 올바르게 파싱하면 99 %의 시간을 낭비 하지 않아도됩니다 ( @yarek의 대답sed 에서 표현이 얼마나 털이 많은지 , 심지어 모든 경우를 다루지 않는지보십시오) . 고맙게도이 경우에는 훨씬 간단한 접근 방식이 있습니다.

find . -name '*(1).m4a' -execdir sh -c \
'for arg; do mv "$arg" "${arg%(1).m4a}".m4a; done' _ {} \+

깔끔한 접근 아직 나오지도 표현 : 1로 털이로
yrk

1
여기에 뭔가 빠졌습니다 ... 어디 done?
yrk

@yarek 캐치 주셔서 감사합니다. 이것과 sed파이프 접근법 의 가장 큰 차이점은 이것이 훨씬 안전하다는 것입니다. 기본적인 쉘 스크립팅 구문을 이해하면 정규식 백 슬래시 수프보다 읽기가 여전히 쉽습니다.
jw013

네가 옳아; 이것은 훨씬 더 깨끗합니다. 그리고 $arg변수는 훨씬 쉽게 읽을 수 있습니다.
hobbes3

1
@DQdlM 위에서 게시 한 스 니펫은 상당히 이식 가능한 POSIX 구문으로 find호출 sh됩니다. 자세한 내용은, 당신은 체크 아웃 할 수있다 매개 변수 확장 섹션설명 화합물 명령에 대한 섹션 for루프를 하고, POSIX의 find사양 . 이러한 자료 외에도 귀하가 가진 특정 질문에 기꺼이 답변 해 드리겠습니다 .
jw013

6

데비안과 우분투에서는 rename 's/\(1\)//' *.m4a문제를 해결하는 데 사용할 수 있습니다 .


이상하게도 할 수는 man rename있지만 실제로는 없습니다 rename: -bash: rename: command not found( which rename아무것도 표시하지 않음).
hobbes3

Mac의 @ hobbes3은 여기서 syscall과 rename (n) -TCL 명령의 이름 바꾸기 (2)를 man -a rename찾습니다 . 도 있습니다 이름 바꾸기 (1)이나 유틸리티가 자체.
yrk

1
IIRC rename는 일부 perl 설치에 포함 된 예제에 포함 된 perl 스크립트이며, 편리한 명령이므로 몇 개의 배포판이 경로에 포함됩니다. (@Hobbes 아마 인터넷에서 찾을 수 있습니다)
Kevin

내 시스템의 @Kevin rename은 정상적인 바이너리입니다 (perl 아님). 그러나 또 다른 경고는 모든 버전의 rename정규 표현식 을 지원 하지는 않는다는 것 입니다. 예를 들어 내가 가지고있는 버전은 직접 문자열을 대체 할 수 있습니다.rename '(1)' '' *.m4a
Patrick

1
Perl rename스크립트는 Debian 및 파생 제품에 의해서만 설치됩니다. 다른 Linux 시스템에는 다른 rename유틸리티가 있습니다 (Patrick에서 표시). OSX는 없습니다.
Gilles 'SO- 악마 그만해'

4

zsh에서 zmv 사용 :

autoload zmv      # you can put this line in your .zshrc
zmv '(*)\(1\)(*)' '$1$2'

두 번째 인자 (새 이름)에서, $1그리고 $2괄호 안의 그룹을 참조 (PATTERN)소스 패턴. 이 이름을 바꾸는 또 다른 방법은

zmv '(*)' '${1/\(1\)/}'

3

다음 접근 방식은 생성 된 명령 실행 하기 전에 미리 보거나 제거 할 수있는 기능을 제공 하며, 이식성 이 뛰어납니다 . bash뿐만 아니라 GNU sed뿐만 아니라 mac에서도 작동해야합니다. find(1) 명령이 없는 시스템에서도 문제없이 (1)로 대체 할 수 있습니다 du.

find . -name '*(1).m4a' |
sed 's/\(.*\)(1).m4a$/mv & \1.m4a/' 

인쇄 된 명령에 만족하면 | sh -x추가 된 상태로 다시 실행하십시오 .

파일 이름에 공백에 대해 우려하는 경우, 다른 추가 의를 모든 공간을 탈출 :

find . -name '*(1).m4a' |
sed -e 's/ /\\ /g' -e 's/\(.*\)(1).m4a$/mv & \1.m4a/'

다른 특수 문자가 예상되면 조금 까다로워집니다.

find . -name '*(1).m4a' |
sed -e "s/'/'\\\\''/g" -e 's/\(.*\)(1).m4a$/mv '\''&'\'' '\''\1.m4a'\'/

첫 번째 함수는 모두 이스케이프 된 문자열 '의 중간에 문자 그대로 사용되도록 모든 형식으로 변환 '...'합니다. 두 번째 함수는 인수가 안에 포함 된 mv 명령을 생성 합니다 '...'.


1
이 명령은 파일 이름 (공백 (, 및 기타 모든 특수 문자)을 이스케이프 처리하지 않거나 파일 이름 주위에 따옴표를 추가 하지 않습니다 . 명령을 수정하려고 시도했지만 명령의 두 파일 이름 주위에 따옴표를 추가하는 방법을 알 수 없었습니다 mv. 명령의 결과 출력 중 하나는 mv ./The Beatles - Let It Be (MFSL LP 1-109) 24-96 Vinyl Rip/01 Two Of Us(1).m4a ./The Beatles - Let It Be (MFSL LP 1-109) 24-96 Vinyl Rip/01 Two Of Us.m4a입니다. 그리고 그 명령을 실행하면 얻을 수 -bash: syntax error near unexpected token '('있습니다.
hobbes3

이것은 숙제라고 생각되지만 :) 좋아, 나는 대답을 업데이트 할 것이다
yrk

그런데 GNU sed는 e대체 후 명령 을 추가하여 명령 자체를 실행할 수 있습니다 . 예를 들어에 find . -name '*(1).m4a' | sed 's/\(.*\)(1).m4a$/mv & \1.m4a/e'배관하지 않고 명령을 실행합니다 sh -x.
러쉬

@Rush 그것이 유일한 sed입니다. 어쨌든 쉘을 시작해야하지만, 각 명령마다 새로운 명령이 필요합니다 ( make의 문제를 생각 나지 않습니까?)
yrk

2
나는 우리가 downvoting해야한다고 생각하지 않습니다. 결국 유효한 솔루션입니다.
hobbes3

1

이를 수행하는 작은 스크립트는 다음과 같습니다.

for var in `find . -type f -name "*(1).m4a"`; do
    new=`echo $var | cut -d'(' -f1`;
    mv $var $new.m4a;
done

이것은 이름에 공백이있는 파일을 질식시킵니다. 또한`find ...`
yrk
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.