Shell-Script

查找該文件名的多個變體同時存在於同一目錄中的文件

  • March 24, 2017

我想列出給定目錄中所有這些文件中存在的文件:

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

我目前正在使用findand 進行操作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、 twosed和 a 。while read

幾乎 30K 的文件需要 >35 秒!我該如何改進它?

例子

如果目錄中有名為AR0505.are、和的文件AR0505.tis,則腳本將列印“AR0505”。AR0505.wed``AR0505LM.bmp

如果這些文件中的一個或多個失去,則腳本不會列印它。

我認為主要的瓶頸是你產生的程序數量。這是一個簡單的腳本,它一次性列出和過濾您的目錄:

#!/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";
   }
}

如果我理解正確,您正在查找每個目標副檔名中存在的所有文件名。如果是這樣,你可以這樣做:

( 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:這是一個特定於 bash 的選項,如果沒有找到匹配的文件,它會使 glob 擴展為空字元串而不是它們自己。那裡只是為了確保該( )選項僅為此命令設置並且不會影響父 shell。
  • for i in *.wed; do ...; done: 遍歷目前目錄中名稱以 . 結尾的所有文件或目錄,將每個文件或目錄.wed保存為$i.
  • "${i//.wed}": 不帶.wed副檔名的文件名。
  • set -- "${i//.wed}"{.tis,.are,LM.bmp}*: 大括號將擴展為foo.tis,foo.are等等,*這是讓 bash 嘗試將它們匹配為 glob 的技巧。這意味著它僅在實際文件名存在時才有效。
  • [[ $# -eq 3 ]] && printf '%s\n' "${i//.wed}": 如果 中正好有 3 個文件$@,那麼除了原來的3 個文件.wed,列印不帶副檔名的文件名。

如果要列印所有 4 個文件名,包括副檔名,只需printf '%s\n' "${i//.wed}"printf '%s\n' "$i".

引用自:https://unix.stackexchange.com/questions/352899