파일 이름의 문자열을 대체하기 위해 find 및 sed를 사용하는 데 어려움을 겪음

파일 이름의 문자열을 대체하기 위해 find 및 sed를 사용하는 데 어려움을 겪음

다음과 같은이 게시물참고로 오류 없이 findand 명령을 실행할 수 있지만 파일 이름은 동일하게 유지됩니다.sed

옷을 벗으려고 노력 중발음 _de_현재 디렉토리의 모든 mp3:

pronunciation_de_wählen.mp3
pronunciation_de_wange.mp3
pronunciation_de_weil.mp3
pronunciation_de_werden.mp3
pronunciation_de_zentrum.mp3

명령 문제를 해결하기 전에 빠른 상태 확인: find . -name "*.mp3"
현재 디렉터리의 모든 mp3를 반환합니다. 이제 이 부분이 작동한다는 것을 알았으니 계속하세요...

sed --version반품sed (GNU sed) 4.4

난 달린다find . -name "*.mp3" -exec sed -i 's/pronunciation_de_//g' {} \;

무슨 일이 일어나고 있는지 완전히 이해했는지 확인하려면 다음을 수행하세요.

find .달리다찾다현재 디렉터리의 명령입니다.
-name "*.mp3"모든 .mp3 파일 형식을 반환합니다.
-exec입력한 다음 명령을 실행합니다.
sed -i이것-나전환이란 (임시) 복사본이 아닌 실제 파일에서 작업하는 것을 의미합니다.

을 위한 's/old_word/new_word/g':

  • 이것에스sed를 대체 모드로 설정합니다.
  • /오래된 단어바꾸려는 단어입니다.
  • /새 단어바꾸려는 단어입니다. 내 예에서는 비어 있습니다.
  • /G첫 번째 일치 항목뿐만 아니라 모든 일치 항목에 대체를 적용합니다.

{}이 문자열은 각 반복 중에 파일 이름으로 대체됩니다.
\;세미콜론 종료됨찾다주문하다. 백슬래시는 세미콜론 문자를 이스케이프하여 쉘이 문자 그대로 해석하는 것을 방지합니다.

나는 이 정보의 대부분을 임의의 블로그와 Stack Exchange 게시물에서 얻습니다.

-exec 옵션 이해find
find의 -exec 명령에서 {} +는 무엇을 의미하나요?

거의 확실히 중복되는 이 질문을 게시하기 전에 시간을 내어 실험하고 조사하고 싶지만 완전히 막혔습니다!

답변1

find -exec ...한 줄짜리 쉘 스크립트를 사용하여 교체를 수행 할 수 있습니다 .

find . -name "*.mp3" -type f -exec bash -c 'mv "$1" "${1/pronunciation_de_}"' bash {} \;

파일 이름은 실행 중인 bash 프로세스에 {}매개변수로 전달되며 , bash의 매개변수 확장 기능이 사용되며, in이 처음 나타나는 경우 빈 문자열로 대체됩니다 .$1${1/pronunciation_de_}pronunciation_de_$1

추가 옵션을 사용하면 -type f일반 파일만 일치하는지 확인할 수 있습니다.

답변2

pronunciation_de_이름이 로 끝나는 모든 파일에서 접두사를 제거 하려면 .mp3이름이 일치하는 파일을 검색하여 pronunciation_de_*.mp3실수로 다른 파일 이름을 수정하지 않도록 해야 합니다(이런 일이 일어날 가능성은 낮음).

줄 중심 텍스트 편집 도구(예: sed파일 이름)를 사용하지 마십시오. 쉘은 파일 이름에서 접두사 및 접미사 문자열을 효율적으로 제거하는 방법을 알고 있습니다.

다음을 사용하여 find문제를 해결할 수 있습니다.

find . -type f -name 'pronunciation_de_*.mp3' -exec sh -c '
    for pathname do
        newname=${pathname##*/}              # removes directory path, leaves filename
        newname=${newname#pronunciation_de_} # deletes the prefix string

        mv -i "$pathname" "${pathname%/*}/$newname"
    done' sh {} +

이 명령은 전달 및 테스트된 파일 find의 경로 이름을 생성 하고 이러한 파일을 일괄적으로 짧은 인라인 스크립트에 공급합니다.-type-namesh -c

이 스크립트는 주어진 경로 이름을 반복하고 각 경로 이름에 대한 새 이름을 만듭니다.

  1. 초기 디렉토리 경로를 제거하고 경로 이름을 다음 ./some/path/pronunciation_de_werden.mp3으로 변경하십시오.pronunciation_de_werden.mp3
  2. 접두사 문자열을 제거 pronunciation_de_하고 pronunciation_de_werden.mp3가 됩니다 werden.mp3.

이 명령은 원본 mv파일을 원본 디렉터리의 새 이름으로 이동하여 원본 파일 ( ${pathname%/*}원래 경로 이름으로 확장될 디렉터리 경로)의 이름을 바꿉니다.

답변3

당신의:

find . -name "*.mp3" -exec sed -i 's/pronunciation_de_//g' {} \;

파일 찾기(다음을 포함한 모든 유형정기적인,목차,심볼릭 링크,선입선출...), 이름은 현재 작업 이하로 끝나며 .mp3, 각 파일은 프로그램과 발견된 파일을 작업할 파일로 사용하여 sed내부 모드에서 실행됩니다 .s/pronunciation_de_//g

그러나 sed그것은 s스트림 editor입니다. 그 임무는 텍스트 스트림을 편집하는 것입니다. 파일을 인수로 주면개울~이다콘텐츠파일 이름(이름이 아님)으로 sed파일 이름이 바뀌지는 않습니다. 파일 이름을 바꾸기 위한 표준 명령은 입니다 mv. 여기에는 특히 일괄 이름 바꾸기를 위한 일부 명령이 포함될 수 있습니다(파일을 찾고 이름을 편집하는 기능이 내장되어 있을 수도 있음). mmv, rename, zmv.

sed해당 이름을 스트림으로 제공하면 이를 사용하여 파일 이름을 편집할 수 있지만 이는 매우 번거롭고 안정적으로 수행하기 어려울 수 있습니다 .

LC_ALL=C find . -depth -name 'pronunciation_de_*.mp3' -exec sh -c '
  ret=0
  for file do
    new_file=$(
      printf '%s\n' "$file" |
        sed "
          :1
          \$!{
            N
            b1
          }
          s|/pronunciation_de_\([^/]*\)\$|/\1|
        "
    )
    mv -i -- "$file" "$newfile" || ret=$?
  done
  exit "$ret"' sh {} +

(테스트되지 않음)

다음 사항이 어떻게 필요한지 참고하세요.

  • LC_ALL=C파일 이름이 로케일의 문자 인코딩으로 인코딩되지 않는 문제를 방지합니다.
  • -depth나뭇잎을 다루기 전에 가지를 처리하십시오.
  • sed파이프( )를 통해 |파일 경로를 제공 하고 다른 파이프( )를 통해 출력을 쉘 변수로 수집 할 수 있도록 셸을 실행합니다 $(...).
  • 한 번에 한 라인만 처리 하고 sed파일 경로는 여러 라인으로 구성될 수 있으므로 sed교체를 수행하기 전에 패턴 공간에 모든 라인을 누적하도록 지시해야 합니다.
  • 파일의 기본 이름만 바뀌고 이전 경로 구성 요소는 바뀌지 않습니다.
  • -i이 옵션을 통해 사용자에게 데이터 손실을 방지할 수 있는 기회를 제공하십시오 . 그러나 이름이 지정된 파일 ./pronunciation_de_weil.mp3과 이름이 지정된 디렉토리가 있으면 여전히 도움이 되지 않습니다. ./weil.mp3이 경우 파일 이름은 자동으로 변경됩니다 ./weil.mp3/pronunciation_de_weil.mp3. GNU 구현에는 이러한 상황을 완화할 수 있는 옵션이 mv있습니다 .-T

zmv(쉘의 자동 로딩 기능)과 비교 zsh:

autoload zmv
zmv '(**/)pronunciation_de_(*.mp3)' '$1$2'

여기에는 또 다른 이점이 있습니다.

  • 실행하기 전에 잠재적인 충돌을 확인하세요.어느이름 바꾸기
  • 숨겨진 파일을 건너뜁니다(숨겨진 파일의 이름도 바꾸려는 경우 이를 변경할 수 있습니다 zmv '(**/)pronunciation_de_(*.mp3)(#qD)' '$1$2').

1 sed구현이 이 비표준 확장을 지원하고 다음 매개변수가 백업 접미어로 간주되지 않는다고 가정합니다.

답변4

일괄 작업의 경우 GNU Parallel을 선호합니다.

ls -1 *.mp3 |
  sed 's/pronunciation_de_//' |
  parallel mv pronunciation_de_{} {}

sed파일 이름에서 콘텐츠를 제거했습니다 pronunciation_de_. 그러면 , , ... {}처럼 될 것입니다.wählen.mp3wange.mp3

관련 정보