Shell-Script
查找該文件名的多個變體同時存在於同一目錄中的文件
我想列出給定目錄中所有這些文件中存在的文件:
<filename>.wed
<filename>.tis
<filename>.are
<filename>LM.bmp
我目前正在使用
find
and 進行操作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"
.