특정 디렉토리에 있는 모든 파일을 나열하고 싶습니다.
<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.tis
etc. 로 확장됩니다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.XXX
OP는 이에 대해 명확하지 않기 때문입니다.
답변4
perl -le '
while ( <*LM.bmp> ) {
(my $f = $_) =~ s|LM\.bmp$||;
print $f if 3 == grep { -e $f . $_ } qw/.tis .are .wed/;
}
'