
複数のファイル拡張子をカンマ区切り文字列として使用し、それを使用して特定のディレクトリ構造のファイルを一覧表示するスクリプトを作成していますが、提供される拡張子の数は異なる場合があります。
私が使用するfindコマンドは次のとおりです。
find ./ -type f \( -iname \*.ksh -o -iname \*.cfg \)
ここでユーザーはkshファイルとcfgファイルを検索しています。ただし、ユーザーはksh、cfg、またはそれ以上の拡張のみを見つけることができます。複数の拡張機能に共通の検索パターンを作成する方法はありますか?
答え1
ファイル名のサフィックスを別のコマンドライン引数として取得したとします(カンマ区切り文字列の処理方法については、回答の最後を参照してください)。
#!/bin/sh
for suffix do
set -- "$@" -o -iname "*.$suffix"
shift
done
shift
find . -type f \( "$@" \)
スクリプトが呼び出されます。
./script.sh ksh cfg
$suffix
位置パラメータのすべてのサフィックスを-o -iname "*.$suffix"
。
shift
通話前の唯一の文字は、削除済みfind
の-o
最初の文字です"$@"
。
ksh93
またはで配列を使用するbash
:
#!/bin/ksh
name_opts=()
for suffix do
name_opts+=( -o -iname "*.$suffix" )
done
find . -type f \( "${name_opts[@]:1}" \)
inは配列の最初の(初期)要素を:1
削除します。"${name_opts[@]:1}"
name_opts
-o
サフィックスをカンマで区切られた文字列としてインポートする場合(つまり、RCSまたはCVSリポジトリのファイルなど、ファイル名のサフィックスにカンマを含むファイルを見つけるためにスクリプトを使用できないことを意味します)、文字列を変換できます。$list
、配列として、bash
またはksh93
set -f
suffixes=( ${list//,/ } )
set +f
sh
または
set -f
set -- $( printf '%s\n' "$list" | tr ',' ' ' )
set +f
または
set -f; ifs=$IFS; IFS=','
set -- $list
set +f; IFS=$ifs; unset ifs
(これらは位置パラメータをサフィックスリストに設定します。)
このset -f
ファイル名は、カンマを置き換えるスペースに文字列を分割するためにシェルに依存するために生成されます(ワイルドカード)。いいえワイルドカードには生成された単語を使用します。それ以外の場合、またはなどのサフィックスの要求をset -f
正しく処理できません。[ch]
*
bash
ループはまたは次ksh
から始まります。
for suffix do ...
到着
for suffix in "${suffixes[@]}"; do ...
そしてループはsh
そのまま残ります。
答え2
拡張正規表現を使用して複数のセグメントを-iregex
置き換えることができます。-iname
グヌfind
:
find . -type f -regextype egrep -iregex '.*\.(ksh|cfg)$'
無料BSD find
:
find -E . -type f -iregex '.*\.(ksh|cfg)$'
変数にすでにカンマ区切りの拡張子がある場合(たとえば$csep
)、それを正規表現の置換(|
)に変換します。最初。例えば
csep='ksh,sh,cfg,csv'
re="$(echo "$csep" | tr , '|')"
find . -type f -regextype egrep -iregex ".*\.($re)$"
#BSD: find -E . -type f -iregex ".*\.($re)$"
コンマ付きの拡張をサポートする必要がある場合は、代わりにをsed
使用してtr
バックスラッシュでエスケープされたコンマ(\,
)を許可できます。例えば
$ csep='ksh,sh,cfg,csv,c\,v'
$ re="$(echo "$csep" | sed -Ee 's/([^\]),/\1|/g')"
$ printf '%b\n' "$re"
ksh|sh|cfg|csv|c\,v