Mac OS X에서 find 및 sed(찾기 및 바꾸기)로 인해 잘못된 바이트 시퀀스가 ​​발생함

Mac OS X에서 find 및 sed(찾기 및 바꾸기)로 인해 잘못된 바이트 시퀀스가 ​​발생함

특정 파일 형식(.mkv, .mp4, .avi)에 대해서만 디렉토리에서 밑줄 찾기 및 바꾸기를 수행하려고 합니다. 다음은 제가 사용하고 있는 코드입니다(Mac OS X 10.9를 사용하고 있습니다).

find . \( -name '*.mp4' -o -name '*.mkv' -o -name '*.avi' \) -print0 | 
    xargs -0 sed -i '' -e 's/\./_/g'

두 가지 솔루션을 읽었지만 둘 다 작동하지 않습니다.

먼저 ~/.bash_profile에 다음을 추가했습니다.

export LC_CTYPE=C 
export LANG=C

이로 인해 동일한 오류가 발생하여 다음을 사용해 보았습니다.

LC_ALL=C sed ... 

작동하지 않습니다. 다음 오류가 발생합니다.

xargs: LC_ALL=C: No such file or directory

다른 제안이 있나요? 저는 쉘을 처음 접했습니다.

편집하다:이것이 내가 달성하고 싶은 것입니다:

디렉토리를 반복하고 파일 이름의 밑줄을 점으로 바꾸려고 합니다.

예:

random_movie.mp4는 random.movie.mp4여야 합니다.

답변1

여기에서 사용해야 합니다 -exec:

find . \( -name '*.mp4' -o -name '*.mkv' -o -name '*.avi' \) \
    -exec sh -cf 'IFS=._
    for f do d=${f%/*} f=${f##*/}
    [ -n "${f##*_*}" ] && continue
    set -- $f 
    printf "%s\n" "mv \\" "$d/$f \\" "$d/$*"
    done' find.rename.shc {} +

작성된 대로 이는 실행할 때 실행할 명령만 인쇄합니다. 예를 들어 내 디렉터리에서 위 명령을 실행하면 .../media/Videos다음 중 일부가 인쇄됩니다.

mv \
/mnt/bcache/media/Videos/TV/Adventure_Time/Adventure_Time.s05e37.The_Box_Prince.mp4 \
/mnt/bcache/media/Videos/TV/Adventure_Time/Adventure.Time.s05e37.The.Box.Prince.mp4
mv \
/mnt/bcache/media/Videos/TV/Adventure_Time/Adventure_Time.s05e38.Red_Starved.mp4 \
/mnt/bcache/media/Videos/TV/Adventure_Time/Adventure.Time.s05e38.Red.Starved.mp4

이를 달성하려면 다음을 변경해야 합니다.

...
set -- $f
printf "%s\n" "mv \\" "$d/$f \\" "$d/$*"
...

...오직...

...
set -- $f; mv "$d/$f" "$d/$*"
...

일반적으로 파이프를 통해 파일 이름 등을 전달하는 것을 피해야 합니다. 이렇게 하면 파일 이름의 시작과 끝 부분에 있는 구분 기호가 손실되기 때문입니다. 이는 더 이상 매개 변수가 아니고 바이트 시퀀스가 ​​됩니다. 이 -exec옵션을 사용 find하면 실행 중인 프로세스의 하위 프로세스에서 이러한 구분 기호를 유지할 수 있습니다 find. 이는 +다음과 같이 작동합니다 xargs. 특정 ARGMAX상황을 피하기 위해 필요한 경우에만 지정된 하위 프로세스를 실행합니다.

sed문제와 관련하여 다음을 시도해 볼 수 있습니다.

LC_ALL=C xargs sed ...

최소한 xargs환경 변수 선언이 매개변수로 해석되는 것을 방지해야 합니다. 하지만 파일 이름을 편집하는 데는 도움이 되지 않습니다.

마지막으로 언급한 문제는 일반적으로 패턴 공간에 나타나는 불완전한 멀티바이트 시퀀스로 인해 발생합니다. POSIX 사양이 .일치하지 않습니다.부분문자 - 따라서 .*해당 맥락에서 의미를 잃습니다. 로케일을 강제로 적용하면 이 문제가 해결되지만 GNU 명령을 C사용하여 예약/패턴 공간을 지우는 또 다른 옵션이 있습니다 .sedz

관련 정보