Unixシェルスクリプトファイルの最初の行にある一致する文字列に基づいてテキストファイルの名前を変更する

Unixシェルスクリプトファイルの最初の行にある一致する文字列に基づいてテキストファイルの名前を変更する

私はUnixスクリプトに初めて触れました。

最初の行(たとえば、で始まる行)の一致する文字列に基づいてファイルのHDR名前を変更したいと思います。

File.txt次のテキストファイル()があります。

HDR##############################1234###
########################################
########################################

以下は私のコードです。パターンで始まり、HDRパターンがあるファイルの最初の行について私のコードでより具体的にチェックするにはどうすればよいですか12345678

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.txtPattern1-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)

関連情報