디렉터리 탐색, 트리 비교, 한쪽에 누락된 파일만 삭제

디렉터리 탐색, 트리 비교, 한쪽에 누락된 파일만 삭제

.mp3해당 폴더에 일치하는 파일이 없는 디렉터리 계층 구조의 파일 과 .jpg .png 파일에 해당 파일이 없는 계층 구조의 다른 파일을 삭제하는 방법을 알아내려고 합니다.` , 등. )/out/.flac/in//out/in/'. The only extension to mutate here are those two but there will be other files (like,

#!/bin/bash
find /in>/tmp/in.txt
sed 's/.flac/.mp3/g; s+/in+/out+g' /tmp/in.txt>/tmp/inx.txt
find /out>/tmp/out.txt
grep -vxF -f /tmp/inx.txt /tmp/out.txt>/tmp/clean.txt
while read line; do rm "$line"; done < /tmp/clean.txt

마지막으로 빈 폴더를 정리합니다. 이 줄은 빈 디렉토리를 제거하는 약간의 "속임수"입니다. 위의 "rm"을 사용하여 위의 파일이나 폴더를 삭제할 수 있다면 더 좋겠지만 이렇게 하면 위험할까요?

find /out/. -depth -type d -exec rmdir {} + 2>/dev/null

지금까지 나는 처음 두 개가 다음과 같이 병합될 수 있다는 것을 발견했습니다.

find /in | sed 's/.flac/.mp3/g; s+/in+/out+g'>/config/inx.txt

나는 다음을 사용하려고합니다 :

grep -vxF -f /tmp/inx.txt `find /out`>/tmp/clean.txt

하지만 오류가 발생합니다. 매개변수 목록이 너무 깁니다.

이 모든 것을 하나로 모아서 처리 시간을 절약할 수 있는 방법이 있습니까? 지금까지는 완료하는 데 약 10분 정도 걸립니다.


다음 시도는 작은따옴표가 있는 파일/폴더를 제외하고 작동합니다(IFS는 최소한 공백을 처리할 수 있음).

#!/bin/bash
IFS=$'\n'; set -f
for mp in $(find /out)
do
    mf="${mp%/out/}/in/"  # Change /out/ to /in/
    ff="${mf%mp3}flac"    # Convert mp3 filename to flac
    [[ ! -f "$ff" ]] && echo rm "$mp"
done
unset IFS; set +f

괜찮은. 내 생각엔 이것이다. 이 시점에서 음악 파일 이상의 것을 확인한다는 점을 반영하도록 원래 질문을 편집했습니다.

#!/bin/bash
find /out -type f -name '*' -exec bash -c '
    for mp in "$0" "$@";
    do
        mf="${mp#/out/}";               # Strip /out/ base prefix leaving relative pathname
        if [ "${mf##*.}" = "mp3" ]; then
                mf="${mf%.mp3}.flac";   # convert filename to flac if it was mp3
        fi;
        [[ ! -f "/in/$mf" ]] && echo rm "$mp";
    done
' {} +

Bash 약어가 어떻게 작동하는지 이해해보세요.

#!/bin/bash
find /out -type f -exec bash -c '
    for mp in "$0" "$@";
    do
        mf="${mp#/out/}";       # Strip /out/ base prefix leaving relative pathname
        [[ "${mf##*.}" == "mp3" ]] && mf="${mf%.mp3}.flac";     # convert filename to flac if it was mp3
        [[ ! -f "/in/$mf" ]] && echo rm "$mp";      # remove /out/ file if no match
    done
' {} +

답변1

grep또는 를 사용할 필요가 없습니다 sed. 프로세스의 본질은 다음과 같이 단일 디렉터리에 대해 표시될 수 있습니다.

#!/bin/bash
for op in /out/*.mp3
do
    mp="${mp##/out/}"       # Strip /out/ base prefix leaving relative pathname
    fp="${mf%.mp3}.flac"    # Convert mp3 name to flac
    [[ ! -f "/in/$fp" ]] && echo rm "$op"
done

디렉터리 트리에 이 내용이 필요하므로 각 디렉터리에 차례로 적용해야 합니다.

find /out -type f -name '*.mp3' -exec bash -c '
    for mp in "$0" "$@";
    do
        mp="${mp#/out/}";
        fp="${mf%.mp3}.flac";
        [[ ! -f "/in/$fp" ]] && echo rm "$op";
    done
' {} +

find지원하지 않으면 두 경우 모두 올바른 파일을 삭제한 다음 만족스러우면 삭제 -exec ... +합니다 +.';'echo

관련 정보