
ある場所から別の場所にファイルをコピーしようとしています。以下はいくつかの例です。
aaa_bbb_ccc_ddd_cost_code_20140330.gz
aaa_bbb_ccc_ddd_revenue_zone_20140329.gz
aaa_bbb_ccc_ddd_benefit_extract_20140330.csv.gz
aaa_bbb_ccc_ddd_profit_zone_20150509.csv.gz
aaa_bbb_ccc_ddd_loss_zone_20140330.csv
aaa_bbb_ccc_ddd_username.csv.gz
上記のリストからコピーする必要があるファイルは、次の形式でなければなりません。
aaa_bbb_ccc_ddd_cost[or]revenue[or]benefit[or]profit[or]loss_yyyymmdd.csv.gz
これはファイルを意味します。
aaa_bbb_ccc_ddd_loss_zone_20140330.csv
aaa_bbb_ccc_ddd_username.csv.gz
コピーしないでください。
また、変数に割り当てる必要がありますが、次のように試していますが、うまくいかないようです。
FILENAME="egrep 'aaa_bbb_ccc_ddd_(cost|revenue|benefit|profit)_code_[0-9]{8}.csv.gz'"
変数に割り当てる理由は、後で次のようにコードで使用する必要があるためです。
SOURCE_DIR="/temp"
DESTN_DIR="/output"
FILENAME=`egrep 'aaa_bbb_ccc_ddd_(cost|revenue|benefit|profit)_code_[0-9]{8}.csv.gz'`
echo "FILENAME is:" $FILENAME
for SAMPLE_FILE in $(ls "$SOURCE_DIR/$FILENAME")
do
cp $SAMPLE_FILE $DESTN_DIR
done
これを達成する他の方法はありますか?
答え1
Usefind
と-exec
そのオプション(ここではGNUを述語find
として使用-regex
):
find . -regextype posix-egrep -regex '.*/aaa_bbb_ccc_ddd_(cost|revenue|benefit|profit|loss)_[[:alpha:]]+_[0-9]+\.csv\.gz' -exec mv {} "$DESTN_DIR" \;
メモ:
find .
find
現在のディレクトリから検索するファイルを知らせます。デフォルトでは、GNUは
find
emacsスタイルの正規表現を使用します。私はを好む-regextype posix-egrep
が、サポートされているおなじみのスタイルに切り替えることができます。正規表現を使用してファイルを選択します。
-regex '.*/aaa_bbb_ccc_ddd_(cost|revenue|benefit|profit|loss)_[[:alpha:]]+_[0-9]+\.csv\.gz'
標準プレフィックスaaa_bbb_ccc_ddd_
の後に指定された単語の1つ(cost|revenue|benefit|profit|loss)
、指定されていない他の単語、_[[:alpha:]]+
日付、_[0-9]+
最後に希望の拡張子が続きます.csv.gz
。これを微調整する必要があるかもしれません。見つかったすべてのファイルはターゲットディレクトリに移動されます
-exec mv {} "$DESTN_DIR" \;
。一致するファイルが見つかったら、find
このコマンドを実行して{}
ファイルの名前を変更します。これは、ファイル名にスペース、改行、またはその他の読み取れない文字が含まれている場合にも機能します。
正規表現を使用したデフォルト(emacs)スタイル
GNU正規表現のデフォルトスタイルには、find
グループ化と代替演算子のいくつかのエスケープが必要です。
find . -regex '.*/aaa_bbb_ccc_ddd_\(cost\|revenue\|benefit\|profit\|loss\)_[[:alpha:]]+_[0-9]+\.csv\.gz' -exec echo mv {} targetdir \;
アップルコンピュータ
Mac OSX バージョンfind
(マニュアルページはこちら)はサポートされていますが、-regex
サポートされていません-regextype
。しかし、正規表現の構文に少しの変更が必要な場合でも驚くことはありません。
IBM AIX 5
IBM AIXバージョンのマニュアルページfind
は次のとおりです。ここ。もちろんいいえサポートする-regex
。
答え2
そしてzsh
:
setopt extendedglob
source_dir="/temp"
destn_dir="/output"
pattern='aaa_bbb_ccc_ddd_(cost|revenue|benefit|profit)_code_[0-9](#c8).csv.gz'
print -r "pattern is: $pattern"
cp -- $source_dir/$~pattern $destn_dir
ksh93パターンは次のように表現できます。
aaa_bbb_ccc_ddd_@(cost|revenue|benefit|profit)_code_{8}(\d).csv.gz
そしてksh88
:
aaa_bbb_ccc_ddd_@(cost|revenue|benefit|profit)_code_[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].csv.gz
しかし、拡大するPOSIX互換性が壊れるのを防ぐために、ワイルドカードは変数内で機能できません。
echo @(a)
これはPOSIXに準拠した誤った構文なので、ksh
新しいglob演算子にすることができます。しかし:
x='@(a)'
echo $x
POSIXで指定されたものと正確に一致し、現在のディレクトリから呼び出されているファイルでは@(a)
なく出力(IFSのデフォルト値を使用)を意味します。a
a
eval
したがって、以下を使用する必要があります。
pattern='aaa_bbb_ccc_ddd_@(cost|revenue|benefit|profit)_code_{8}([0-9]).csv.gz'
print -r "pattern is: $pattern"
eval 'cp -- "$source_dir"/'"$pattern"' "$destn_dir"'
答え3
これは1行で実行できます。
find /temp -maxdepth 1 -type f | \
grep -P 'aaa_bbb_ccc_ddd_(cost|revenue|benefit|profit)_.*[0-9]{8}' | \
xargs cp -t /output
find
サブフォルダがないフォルダの内容を一覧表示します。grep
あなたのファイル名cp
ターゲットディレクトリ(-t
)にコピーします。
質問は100%明確ではないので、正規表現を調整するだけです。ある文書にはそのような内容があり.csv.gz
、ある文書にはあり.csv
、ある文書にはあります.gz
。
答え4
すべての最新のシェルは、デフォルトのglob構文を使用せずに、次のようなものを直接サポートします。
cp aaa_bbb_ccc_ddd_{cost,revenue,benefit,profit,loss}_[0-9]*.csv.gz destination_dir
これは5つの引数に拡張され、各引数は次の形式の球です。..._keyword_<digits>...
2番目の質問に答えるために、各変数を順番に変数に割り当てる方法は次のとおりです。
for FNAME in aaa_bbb_ccc_ddd_{cost,revenue,benefit,profit,loss}_[0-9]*.csv.gz
do
echo $FNAME
if [ -e $FNAME ]
then
cp $FNAME <destination>
fi
done
プレゼンスチェック(if [ -e $FNAME ]
)は、5つのグローブのうちの1つが一致しない場合、グローブをそのまま維持し、エラーメッセージを受け取るために発生します。