検索:大容量ファイル名のリストを効率的に検索する方法

検索:大容量ファイル名のリストを効率的に検索する方法

いくつかのリストで、デフォルトの名前が指定されている何百ものファイルを見つける必要があります(と呼びますbaseNames)。次に、基本名+指定された3つの拡張子を検索する必要があります。

例:入力リストから抽出されたデフォルト名の1つがで、指定されたFOO拡張子が.txt、、.csvと仮定されます.py。だから、、FOO.txtを見つける必要がありますFOO.csvFOO.py

私のbashスクリプトの現在の方法は次のとおりです。

for bn in ${baseNames}; do
  find ${searchDir} '(' -name "$bn.txt" -o -name "$bn.csv" -o -name "$bn.py" ')'
done

これは機能しますが、非効率的です。各デフォルト名に対してジョブfind全体を再実行する必要があります。searchDirこれにはかなりの数のファイルが含まれているため、時間がかかります。

findオプションまたはパイプで検索する必要があるファイルのリストを提供する方法はありますか?

明らかに知っているが、-name ... -or何百ものファイルがある場合、このアプローチは明らかに実用的ではありません。単純化のために拡張子を無視することもできます。 find.

ベストアンサー1

配列を使用してください。例えば

#!/bin/bash

baseNames=(FOO BAR BAZ)

findNames=('(')
for bn in "${baseNames[@]}"; do
  for ext in txt csv py; do
    findNames+=("$bn.$ext" '-o' '-name')
  done
done
# replace the final '-o' and '-name' in the array with a close parenthesis
unset 'findNames[-1]'
findNames[-1]=')'
# If using a version of bash before v4.3, use:
#unset 'findNames[${#findNames[@]}-1]'
#findNames[${#findNames[@]}-1]=')'


declare -p findNames

出力は次のようになりますdeclare -p(改行とスペースを追加して読みやすくなりました)。

declare -a findNames=(
  [0]="("
    [1]="-name" [2]="FOO.txt" [3]="-o" [4]="-name" [5]="FOO.csv"
    [6]="-o" [7]="-name" [8]="FOO.py" [9]="-o" [10]="-name" [11]="BAR.txt"
    [12]="-o" [13]="-name" [14]="BAR.csv" [15]="-o" [16]="-name" [17]="BAR.py"
    [18]="-o" [19]="-name" [20]="BAZ.txt" [21]="-o" [22]="-name" [23]="BAZ.csv"
    [24]="-o" [25]="-name" [26]="BAZ.py"
  [27]=")"
)

で配列を使用するには、find次のことが必要です。

searchDir="./"
find "$searchDir" "${findNames[@]}"

これにより、次のfindコマンドが実行されます(読みやすくするために改行が追加されました)。

find ./ ( -name FOO.txt -o -name FOO.csv -o -name FOO.py \
  -o -name BAR.txt -o -name BAR.csv -o -name BAR.py \
  -o -name BAZ.txt -o -name BAZ.csv -o -name BAZ.py )

そしてここでエスケープする必要はありません。なぜなら、シェルはそれをサブシェルの起動を指示するのではなく、リテラル引数(配列はbash拡張)として扱うからです()シェルに入力する場合は、エスケープまたは引用する必要があります。

おすすめ記事