동일한 디렉토리에서 파일 이름이 여러 변형된 파일 찾기

동일한 디렉토리에서 파일 이름이 여러 변형된 파일 찾기

특정 디렉토리에 있는 모든 파일을 나열하고 싶습니다.

  • <filename>.wed
  • <filename>.tis
  • <filename>.are
  • <filename>LM.bmp

나는 현재 find이것을 사용하고 있습니다 sed. 작동하지만 우아하지 않고 느립니다!

find . -iname "*.wed" -exec echo {} \; | sed s/.wed$// $1 | sed s/..// $1 | while read in; do find . -name "$in.are"; done | sed s/.are$// $1 | sed s/..// $1 | while read in; do find . -name "$in.tis"; done | sed s/.tis$// $1 | sed s/..// $1 | while read in; do find . -name "$in*.bmp"; done

기본적으로 필터링하려는 각 확장자에 대해 a find, two 및 a를 연결합니다 sed.while read

30K 파일은 35초 이상 걸립니다! 어떻게 개선할 수 있나요?

AR0505.are디렉토리에 , AR0505.tis및 이름 AR0505.wed의 파일이 있는 경우 AR0505LM.bmp스크립트는 "AR0505"를 인쇄합니다.

이러한 파일 중 하나 이상이 누락된 경우 스크립트는 해당 파일을 인쇄하지 않습니다.

답변1

내가 올바르게 이해했다면 각 대상 확장자에 대해 존재하는 모든 파일 이름을 찾고 있는 것입니다. 그렇다면 다음과 같이 할 수 있습니다.

( shopt -s nullglob; 
  for i in *.wed; do 
    set --  "${i//.wed}"{.tis,.are,LM.bmp}*; 
    [[ $# -eq 3 ]] && printf '%s\n'  "${i//.wed}"; 
done )

설명하다

  • shopt -s nullglob: 일치하는 파일이 없는 경우 glob이 자체가 아닌 빈 문자열로 확장되도록 하는 bash 관련 옵션입니다. ( )옵션이 해당 명령에 대해서만 설정되고 상위 쉘에 영향을 주지 않도록 하기 위해서만 존재합니다 .
  • for i in *.wed; do ...; done: 이름이 현재 디렉토리로 끝나는 모든 파일이나 디렉토리를 반복하여 .wed각 파일이나 디렉토리를 $i.
  • "${i//.wed}": 확장자가 없는 파일 이름입니다 .wed.
  • set -- "${i//.wed}"{.tis,.are,LM.bmp}*: 중괄호는 foo.tisetc. 로 확장됩니다 foo.are. 이는 *bash가 이를 와일드카드로 일치시키도록 하는 트릭입니다. 즉, 실제 파일 이름이 존재하는 경우에만 작동합니다.
  • [[ $# -eq 3 ]] && printf '%s\n' "${i//.wed}": 에 정확히 3개의 파일이 있는 경우 원본 파일 외에 3개의 파일이 있는 $@경우 확장자 없이 파일 이름을 출력합니다..wed

printf '%s\n' "${i//.wed}"4개의 파일 이름(확장자 포함) 을 모두 인쇄하려면 printf '%s\n' "$i".

답변2

주요 병목 현상은 생성된 프로세스 수라고 생각합니다. 다음은 한 번에 디렉터리를 나열하고 필터링하는 간단한 스크립트입니다.

#!/usr/bin/perl

use strict;
use warnings;

my %files;
my $dir;
my @extensions = ("\.tis","\.are","LM\.bmp","\.wed");

opendir($dir, ".") || die "Error opening dir\n";
while (my $file = readdir($dir)) {
    foreach my $ext (@extensions) {
        if ($file =~ /^(.*)$ext$/sm) {
            $files{$1} += 1;
        }
    }
}
closedir($dir);

foreach my $file (keys %files) {
    if ($files{$file} == scalar(@extensions)) {
        print "$file\n";
    }
}

답변3

find . -type d  -exec sh -c '
   h=$1; cd "$h" || exit
   set -- /dev/nul[l] [f]oobar.{wed,tis,are} [f]oobarLM.bmp; shift
   case $# in 4 ) for arg; do printf "%s/%s\n" "$h" "$arg"; done ;; esac
' {} {} \;

참고: 여기서는 이 4개 파일을 제외한 다른 파일을 살펴보지 않으며, 발견된 경우에만 동일한 디렉터리에 다른 파일이 ALL 4있더라도 해당 파일이 표시됩니다 . foobar.XXXOP는 이에 대해 명확하지 않기 때문입니다.

답변4

perl -le '
   while ( <*LM.bmp> ) {
      (my $f = $_) =~ s|LM\.bmp$||;
      print $f if 3 == grep { -e $f . $_ } qw/.tis .are .wed/;
   }
'

관련 정보