私はUnixスクリプトに初めて触れました。
最初の行(たとえば、で始まる行)の一致する文字列に基づいてファイルのHDR
名前を変更したいと思います。
File.txt
次のテキストファイル()があります。
HDR##############################1234###
########################################
########################################
以下は私のコードです。パターンで始まり、HDR
パターンがあるファイルの最初の行について私のコードでより具体的にチェックするにはどうすればよいですか1234
?5678
if grep -o "1234" File.txt
then mv File.txt Pattern1.txt
echo "File with pattern1 received..."
elif grep -o "5678" File.txt
then mv File.txt Pattern2.txt
echo "File with pattern2 received..."
else
echo "File have no matching pattern..."
fi
答え1
行を読むには「read」を使用し、何をするかを決定するには「case」を使用します。
{
IFS= read -r Firstline
case "$Firstline" in
("HDR"*"1234"*) mv File.txt Pattern1.txt
echo "File with pattern1 received..." ;;
("HDR"*"5678"*) mv File.txt Pattern2.txt
echo "File with pattern2 received..." ;;
(*) echo "Nothing matched" ;;
esac
} < File.txt
答え2
-n
(--line-number
)オプションを使用して線を識別し、grep
パターンcase
を一致させます。
Tmp=$(grep -n "HDR.*[0-9]\{4\}" File.txt)
if [ "${Tmp%:*}" -eq 1 ]
then case "${Tmp#*:}" in
HDR*1234*) NewName="Pattern1";;
HDR*5678*) NewName="Pattern2";;
esac
if [ "$NewName" ]
then mv -- File.txt "$NewName".txt
echo "File with $NewName received..."
else echo "File doesn't have a matching pattern..."
fi
else echo "File doesn't have a pattern in line 1"
fi
答え3
Perlrename
ユーティリティを使用してください。
file-rename
注:Perlの名前変更は、、、またはとも呼ばれperl-rename
ますprename
。機能とコマンドラインオプションが完全に異なり、互換性のないrename
ユーティリティと混同しないでください。util-linux
$ rename -n ' BEGIN {
# This block runs only once when the script starts, there's no need
# to redefine these vars on every pass through the loop. File::Rename
# scripts run with `use strict vars`, so we need to be careful about
# variable scope. See `perldoc -f our`
our %patterns=(1234 => "Pattern1.txt", 5678 => "Pattern2.txt");
our $re = "^HDR#+(" . join("|",keys %patterns) . ")#+$";
};
# The remainder of the script runs once for every filename
our (%patterns, $re); # these vars are in File::Rename lexical scope
open(my $fh,"<",$_); my $line=<$fh>; close($fh);
if ($line =~ /$re/) { $_ = $patterns{$1} }' File*
rename(File1.txt, Pattern1.txt)
rename(File2.txt, Pattern2.txt)
(これは2つのテキストファイル(サンプルデータのコピー)で実行されました。File1.txtにはFile.txtの例と全く同じ1234が含まれていますが、File2.txtは5678を含むように編集されました。
この-n
オプションはテスト的に実行されるため、実際にファイル名を変更せずに実行するアクションのみが表示されます。要件を満たしていることが確認されたら、削除または置換して-n
詳細な出力を取得します。-v
この名前変更スクリプトは、ハッシュを使用して、検索するパターンと%patterns
名前を変更するパターンを含むファイルのファイル名を保存します。変数のハッシュキーに基づいて正規表現を設定します$re
。
次に、現在のファイル名を開き、最初の行を読みます。最初の行がパターンの1つと一致する場合、そのファイル名に名前が変更されます。
これらのハッシュを使用すると、スクリプトをより多くのパターンまたは別のパターンに簡単に拡張できます。ハッシュ%patterns
(およびその中の合計)を^HDR#+(
除いて、何もハードコーディングされません。)#+$
$re
-f
注:またはオプションを使用して--force
強制的に名前を変更しない限り、名前を変更しても既存のファイルは上書きされません。これは、既存のファイルと変更されたばかりのファイルの両方に適用されます。複数のファイルに同じパターンが含まれている場合、最初のファイルの名前のみが変更されます。-f
もちろん を使用すると、既存/以前に名前が変更されたファイルを上書きします。より良い方法は、カウンタ変数(ファイル名やパターンをキーとして使用するハッシュ)を使用してファイル名を等にPattern1.txt.001
変更Pattern1.txt.002
することです。
または、次のfileparse()
機能を使用してくださいファイル::デフォルト名モジュールが到着しましたPattern1-001.txt
。Pattern1-002.txt
しばらくお待ちください。
例えば
$ rename -n 'BEGIN {
use File::Basename;
our %seen=();
our %patterns=(1234 => "Pattern1.txt", 5678 => "Pattern2.txt");
our $re = "^HDR#*(" . join("|",keys %patterns) . ")"
};
our(%seen, %patterns, $re);
open(my $fh,"<",$_); my $line=<$fh>; close($fh);
if ($line =~ /$re/) {
my($name,$path,$suffix) = fileparse($patterns{$1}, qr/\.[^.]*$/);
$_ = sprintf "%s-%03i%s", $name, ++$seen{$1}, $suffix
}' File*
rename(File1.txt, Pattern1-001.txt)
rename(File2.txt, Pattern2-001.txt)
rename(File3.txt, Pattern1-002.txt)