
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 1
directory_name/*.mp3
directory_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