Linux 또는 Windows에서 해당 디렉토리에 있는 유일한 mp3인 모든 mp3의 경로를 어떻게 찾나요?

Linux 또는 Windows에서 해당 디렉토리에 있는 유일한 mp3인 모든 mp3의 경로를 어떻게 찾나요?

Music 폴더가 있고 내용은 다음과 같습니다.

음악
    -아티스트A
        -노래1.mp3
        -앨범A
            -노래2.mp3
            -노래2.m4a
        -앨범B
            -노래1.mp3
            -노래2.mp3
            -노래3.mp3
        -앨범C
            -노래1.mp3
            -노래1.jpg
            -SomeFolder1
                -노래1.mp3
    -아티스트B
        -노래1.mp3
    -아티스트C
        -노래1.mp3
        -노래2.mp3
        -노래3.mp3
        -SomeFolder2
            -노래1.jpg
            -노래2.jpg
        -SomeFolder3


다음과 같은 출력을 찾고 있습니다.

아티스트A/Song1.mp3
아티스트A/앨범A/Song2.mp3
아티스트A/앨범C/Song1.mp3
아티스트A/앨범C/SomeFolder1/Song1.mp3
아티스트B/노래1.mp3



따라서 나는 파일이 하나만 있는 디렉토리를 원하지 않고 하위 디렉토리나 다른 파일에 관계없이 mp3가 하나만 있는 디렉토리를 원합니다. 나는 또한 빈 디렉토리나 하나 이상의 mp3를 포함하는 디렉토리를 원하지 않습니다.

나는 Linux용 쉘 스크립트에 반대하지 않습니다. 그러나 나는 어느 OS에서도 프로그램을 컴파일하고 싶지 않습니다.

나는 시도했지만 find . -type d -exec sh -c 'set -- "$0"/*.mp3; [ $# -le 1 ]' {} \; -print

결과는 다음과 같습니다.

.
./아티스트B
./아티스트A
./아티스트A/앨범A
./아티스트A/앨범C
./ArtistA/AlbumC/SomeFolder1
./ArtistC/SomeFolder2
./ArtistC/SomeFolder3

가깝지만 정확히 내가 원하는 것은 아닙니다. 두 개의 빈 폴더가 있고 파일 이름이 없습니다.

답변1

언뜻 보면 첫 번째 명령이 빈 폴더( *.mp3파일이 없는 폴더) 를 보고하는 이유 는 . MP3 파일이 하나 이하인 디렉터리를 보고하는 것처럼 보입니다. 그러나 변경 하면 작동하지 않습니다. 문제는 하나 이상의 MP3 파일이 있는 디렉토리에서 MP3 파일 이름 목록을 얻지만 파일 이름이 없는 디렉토리에서는 문자 그대로 . 파일과 일치하지 않는 와일드카드가 명령줄에서 사라져야 한다고 쉘에 지시하면 이 문제를 해결할 수 있습니다.-le 1-eq 1-le 1-eq 1directory_name/*.mp3directory_name/*.mp3

찾다 . -d 유형 -exec
        sh -c 'shopt -s nullglob;설정 -- "$0"/*.mp3; [ $# -eq 1 ]' {} \; -인쇄

(모두 한 줄로 입력)

./ArtistA
./ArtistA/AlbumA
./ArtistA/AlbumC
./ArtistA/AlbumC/SomeFolder1
./ArtistB

그러나 파일 수를 계산하는 쉘이 있고 find인쇄를 요청하고 있으며 find디렉토리만 보고 있습니다. 쉘이 보는 파일 이름을 인쇄하도록 하면 어떨까요?

찾다 . -d 유형 -exec
        sh -c 'shopt -s nullglob; 설정 -- "$0"/*.mp3; [ $# -eq 1 ]&& 에코 "$1"' {} \;

(즉, 파일이 하나인 경우 echo첫 번째 파일의 이름( $1))을 입력하면 원하는 결과를 얻을 수 있습니다.

답변2

PowerShell을 사용하는 Windows의 경우 이미 C:\YOUR_PATH 폴더에 있다고 가정합니다.

PS C:\YOUR_PATH> (Get-ChildItem -recurse | Where-Object {$_.name -match ".mp3"}) | Group-Object -Property Directory | Where-Object {$_.Count -eq 1} | ForEach-Object { (Get-ChildItem $_.Name -Filter "*.mp3").FullName}

출력:

C:\YOUR_PATH\ArtistA\Song1.mp3
C:\YOUR_PATH\ArtistA\AlbumA\Song2.mp3
C:\YOUR_PATH\ArtistA\AlbumC\Song1.mp3
C:\YOUR_PATH\ArtistA\AlbumC\SomeFolder1/Song1.mp3
C:\YOUR_PATH\ArtistB\Song1.mp3

파이프된 명령 분석:

현재 디렉터리 아래의 모든 파일과 폴더 가져오기

Get-ChildItem -recurse 

마스크를 기준으로 파일만 일치시킵니다.

Where-Object {$_.name -match ".mp3"})

디렉터리 속성을 기반으로 그룹화 수행

Group-Object -Property Directory 

1개 항목이 있는 디렉터리만 선택

Where-Object {$_.Count -eq 1} 

각 디렉터리에서 파일 마스크와 일치하는 파일 하나의 전체 이름을 추출합니다.

ForEach-Object { (Get-ChildItem $_.Name -Filter "*.mp3").FullName} 

답변3

누군가가 더 나은 방법을 가지고 있다고 확신하지만 이 bash 명령은 Linux에서 작동합니다.

for Folder in $(find . -name "*.mp3" -printf "%h\n")
do
    [[ $(ls -l $Folder/*.mp3 | wc -l) -eq "1" ]] && ls $Folder/*.mp3
done

이 스크립트는 모든 단일 .mp3 파일의 폴더에서 테스트를 수행하며 동일한 파일의 각 일치 항목에 대해 반복됩니다. 예를 들어 Music/ArtistA/AlbumB를 3번 확인합니다. 가지고 있는 mp3 파일 수에 따라 시간이 오래 걸릴 수 있습니다(꽤 큰 라이브러리가 필요함).

그렇다면 약간 더 복잡하게 만들 수 있습니다.

for Folder in $(find . -name "*.mp3" -printf "%h\n" | awk '!x[$0]++')
    do
        [[ $(ls -l $Folder/*.mp3 | wc -l) -eq "1" ]] && ls $Folder/*.mp3
    done

결과는 동일하지만 각 폴더를 한 번만 확인하므로 많은 시간을 절약할 수 있습니다. awk 명령은 중복된 폴더 이름을 제거합니다.

또 다른 참고 사항은 파일이 Linux에서 대소문자를 구분하므로 모든 .MP3또는 .Mp3파일을 완전히 무시한다는 것입니다. 이를 일치시키려면 의 3개 인스턴스를 모두 mp3다음 으로 변경하세요.[mM][pP]3

답변4

답변은 다음과 같습니다.

find Music -name "*.mp3" -exec dirname {} \; |
    sort |
    uniq -c |
        while read count parent
        do
            if [[ $count -eq 1 ]]
            then
                echo "$parent"/*.mp3
            fi
        done

관련 정보