find 명령에 디렉토리 목록을 어떻게 전달합니까?
다음과 같이 목록을 얻는다고 상상해 보세요.
ls -d mydir*/
그러면 mydir1, mydir2 등이 출력되지만 otherdirs1, otherdirs2는 제외됩니다.
목록에서 다음 명령을 실행하고 싶습니다.
find <put here the name of each dir> -type f -name "*.mp3" -print0 | xargs -0 ...
각 디렉터리에서 개별적으로 이 명령을 실행해 보세요.
find -type f -name "*.mp3" -print0 |
xargs -0 mplayer -vo dummy -ao dummy -identify 2>/dev/null |
perl -nle '/ID_LENGTH=([0-9\.]+)/ && ($t +=$1) && printf "%02d:%02d:%02d\n",$t/3600,$t/60%60,$t%60' |
tail -n 1
즉, mp3를 찾고, mplayer를 실행하여 각 파일의 메타데이터를 얻고, 각 mp3 파일에 대한 모든 ID_LENGTH의 합계를 계산하고, 디렉터리에 있는 모든 mp3의 합계를 출력합니다.
답변1
ls -d
전달한 내용을 정확하게 나열하십시오(존재하지 않는 파일 제외). 따라서 이름이 mydir
다음으로 시작하는 디렉토리가 하나 이상 있다고 가정합니다.
find mydir*/ -type f -name .mp3 -print0 | …
mydir*/
디렉토리에 대한 심볼릭 링크가 일치 find
하고 링크된 디렉토리가 순회된다는 점에 유의하세요 .
xargs
가능한 한 적은 수의 매개변수를 사용하여 명령을 실행하고 한 번에 여러 인수를 전달하는 것이 일반적입니다 . 각 파일에 대해 별도로 명령을 실행해야 하는 경우 다음과 같이 지정하십시오.
find mydir*/ -type f -name .mp3 -print0 |
xargs -0 -n1 mplayer … |
perl …
아니면 간단한 작업을 수행하고 -exec
옵션을 사용하십시오 find
. find
오류를 개별적으로 필터링하는 기능은 상실됩니다 mplayer
.
find mydir*/ -type f -name .mp3 -exec mplayer -vo dummy -ao dummy -identify {} \; 2>/dev/null |
perl …
그런데 마지막 줄만 필요한데 왜 모든 줄을 인쇄하는 걸까요?
… | perl -nle '/ID_LENGTH=([0-9\.]+)/ && ($t +=$1); END {printf "%02d:%02d:%02d\n",$t/3600,$t/60%60,$t%60}'
또한 이를 사용하여 run 후 bash shopt -s globstar
, run 후 ksh 또는 기본적으로 zsh에서 하위 디렉터리의 파일을 재귀적으로 일치시킬 수 있습니다.set -o globstar
**
mycommand mydir*/**/*.mp3
for f in mydir*/**/*.mp3; do …
이는 이름이 로 끝나는 디렉토리 및 심볼릭 링크와도 일치합니다 .mp3
. Bash는 디렉터리의 기호 링크를 순회하는 반면, ksh와 zsh는 mydir*
디렉터리의 기호 링크를 순회하지만 반복 시 기호 링크를 생략합니다.
for f in mydir*/**/*.mp3; do
mplayer -vo dummy -ao dummy -identify "$f" 2>/dev/null
done | perl …
ksh93 및 zsh(bash, dash 또는 pdksh 제외)에는 부동 소수점 연산이 있으므로 합계를 계산하기 위해 Perl과 같은 다른 도구를 호출할 필요조차 없습니다.
typeset -F length=0
for f in mydir*/**/*.mp3; do
length+=$(mplayer -vo dummy -ao dummy -identify "$f" 2>/dev/null |
sed -n 's/^ID_LENGTH=//p')
done | perl …
printf "%02d:%02d:%02d\n" $((t/3600)) $((t/60%60)) $((t%60))