파일 확장자를 무시하고 디렉터리 내용을 이름별로 반복적으로 비교합니다.

파일 확장자를 무시하고 디렉터리 내용을 이름별로 반복적으로 비교합니다.

약 7,000개의 음악 파일이 포함된 디렉토리가 있습니다. 나는 Lame을 사용하여 그 안에 있는 모든 파일을 별도의 디렉터리에 재귀적으로 기록하여 동일한 상대 경로와 파일 이름을 가진 모든 파일을 출력했습니다. 출력 파일의 확장자는 .mp3이지만 일부 입력 파일의 확장자는 다릅니다(.wma, .aac 등).

출력 디렉터리에 약 100개 파일이 누락된 파일 수 차이를 볼 수 있습니다. 내가 원하는 것은 두 디렉터리를 비교하여 소스에는 있지만 대상에는 없는 파일 목록을 얻는 것입니다. 파일 확장자의 차이를 무시해야 한다는 점을 제외하면 이는 간단합니다.

테스트 실행을 켠 상태에서 rsync를 사용해 보았지만 파일 확장자를 무시하는 방법을 찾을 수 없습니다. 또한 diff를 시도했지만 이름으로만 확인하고 파일 확장자를 무시하는 옵션을 찾을 수 없습니다. 두 디렉터리 모두에서 재귀 ls를 수행하고 파일 확장자를 제거한 다음 출력을 비교할 수 있다고 생각하기 시작했지만 sed 또는 awk를 사용하여 ls 출력을 수정하는 작업부터 시작해야 할지 모르겠습니다.

답변1

목록을 보려면 하위 디렉터리로 반복되는 것과 그렇지 않은 것의 두 가지 변형이 있습니다. 모두 bash, ksh 및 zsh와 관련된 구문을 사용합니다.

comm -3 <(cd source && find -type f | sed 's/\.[^.]*$//' | sort) \
        <(cd dest && find -type f | sed 's/\.[^.]*$//' | sort)
comm -3 <(cd source && for x in *; do printf '%s\n' "${x%.*}"; done | sort) \
        <(cd dest && for x in *; do printf '%s\n' "${x%.*}"; done | sort)

zsh에서는 더 짧습니다.

comm -3 <(cd source && print -lr **/*(:r)) <(cd dest && print -lr **/*(:r))
comm -3 <(print -lr source/*(:t:r)) <(print -lr dest/*(:t:r))

이 명령은 두 파일( ) , 첫 번째 파일( )에만 또는 두 번째 파일( ) comm에만 공통되는 줄을 나열합니다 . 이 숫자는 출력에서 ​​뺀 내용을 나타냅니다. 두 개의 입력 파일을 정렬해야 합니다.comm -12comm -23comm -13

여기서 파일은 실제로 명령의 출력입니다. 쉘은 <(…)"가짜" 파일(FIFO 또는 /dev/fd/명명된 파일 설명자)을 명령에 대한 인수로 제공하여 이 구성을 평가합니다.

1 그래서 여기마이너스 스피커완벽하게 이해됩니다.


파일에 대한 작업을 수행하려면 소스 파일을 반복해야 할 수도 있습니다.

cd source
for x in *; do
  set -- "…/dest/${x%.*}".*
  if [ $# -eq 1 ] && ! [ -e "$1" ]; then
    echo "$x has not been converted"
  elif [ $# -gt 1 ]; then
    echo "$x has been converted to more than one output file: " "$@"
  else
    echo "$x has been converted to $1"
  fi
done

관련 정보