파일을 재귀적으로 반복할 때 공백이 있는 이름 처리

파일을 재귀적으로 반복할 때 공백이 있는 이름 처리

.mkv하위 폴더가 있는 폴더 구조의 모든 파일을 .mp4.

현재 폴더에만 적용되는 표준 줄이 표시됩니다.

for video in *.mkv; do ffmpeg -i "$video" -acodec aac -ac 2 "${video%.*}".mp4; rm "$video"; done

그래서 나는 다음과 같은 것을 만들 것이라고 생각했습니다.

for video in $(find . -name *.mp4); do ffmpeg -i "$video" -acodec aac -ac 2 "${video%.*}".mkv; rm "$video"; done

그러나 공백이 포함된 폴더에서는 실패하는 것 같습니다. 누구든지 내 실수를 지적할 수 있나요?

답변1

귀하의 실수는 find명령 대체를 사용하는 것입니다. 명령 대체는 항상 단일 문자열을 생성합니다. 대체 항목을 따옴표로 묶지 않으면 문자열이 공백, 탭 및 줄 바꿈(기본적으로)으로 분할됩니다. 분할된 단어는 파일 이름 글로빙을 위해 처리됩니다. 결과 문자열은 루프가 반복되는 문자열이며, 이는 원하는 문자열이 아닙니다.

현재 디렉터리에서 작동하는 루프(대시로 시작하는 파일 이름 문제를 해결하기 위해):

for video in ./*.mkv; do
    ffmpeg -i "$video" -acodec aac -ac 2 "${video%.*}".mp4
    rm "$video"
done

globbing 모드를 활성화하여 재귀적으로 작동하도록 변경되었습니다( 일치 항목이 없을 때 루프가 완전히 실행되는 것을 방지하기 위해 **사용 ).nullglob

shopt -s globstar nullglob

for video in ./**/*.mkv; do
    ffmpeg -i "$video" -acodec aac -ac 2 "${video%.*}".mp4
    rm "$video"
done

위의 두 루프는 파일 유형을 고려하지 않으며 ffmpeg이름이 지정된 패턴과 일치하는 한 심볼릭 링크, 디렉토리 또는 기타 비 전통적인 유형의 파일을 기꺼이 제공합니다.

또는 경로 이름의 재귀 생성을 다음 대상에 위임합니다 find(일반 파일만 선택):

find . -name '*.mkv' -type f -exec sh -c '
    for video do
        ffmpeg -i "$video" -acodec aac -ac 2 "${video%.*}".mp4
        rm "$video"
    done' sh {} +

위의 코드는 또한 패턴과 일치하는 숨겨진 이름을 찾습니다. 이는 처음 두 개의 쉘 루프가 수행하지 않는 것입니다( dotglob쉘 옵션이 활성화되지 않은 경우).

기타 관련 질문:

관련 정보