いくつかのリストで、デフォルトの名前が指定されている何百ものファイルを見つける必要があります(と呼びますbaseNames
)。次に、基本名+指定された3つの拡張子を検索する必要があります。
例:入力リストから抽出されたデフォルト名の1つがで、指定されたFOO
拡張子が.txt
、、.csv
と仮定されます.py
。だから、、FOO.txt
を見つける必要がありますFOO.csv
。FOO.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拡張)として扱うからです(
。)
シェルに入力する場合は、エスケープまたは引用する必要があります。