it-swarm-ja.com

親フォルダ名から複数のファイルの名前を変更するシェルスクリプト

私はこのようなファイル構造を持っています:

  • 00000010
    • 000000001.file1
    • 000000001.file2
  • 00000020
    • 00000003.file1
    • 00000003.file2
    • 00000003.file3
  • .。

したがって、8桁の数字で始まる名前のファイルが1つ以上含まれている8桁の名前のフォルダーがあります。しかし、これらのファイル名は、たとえば、同期していません。だから今私はアーカイブするためにbashでそれらの名前を再帰的に変更しようとしています:

  • 00000010
    • 000000010.file1
    • 000000010.file2
  • 00000020
    • 00000020.file1
    • 00000020.file2
    • 00000020.file3
  • .。

私のスクリプトは次のようになります。

#! /bin/bash

find * -maxdepth 1 -name "*" -type d | while read -r dir
do
        rename 's/$dir\/[0-9]{8}/$dir/' *
done

しかし、これは機能せず、次のようなエラーが発生します

グローバルシンボル「$ dir」には、(eval 1)行1に明示的なパッケージ名が必要です。

フォルダ名に従ってファイルの名前を変更するにはどうすればよいですか?

ご協力ありがとう御座います!

3
Simon

私が学んだ別の答えから、私は使用しなければならないこと

rename "s/$dir\/[0-9]{8}/$dir\/$dir/" $dir/*

誰かが同じ問題を抱えている場合に備えて...

2
Simon

$dirがパターンに補間される答えは本当に好きではありません。ディレクトリが次のようになると、予期しない結果が生じる可能性があります。特別な正規表現トークンとして解釈される文字が含まれています。

むしろ、ファイルをパターン内で直接照合し、ディレクトリをループして通常のglobを使用する必要をなくしたいと思います。

rename 's#([^/]+)/[^/]+(\.file[0-9]+)$#$1/$1$2#' base_directory/*/*

globがディレクトリ内の個々のファイルにヒットする場所(base_directory/*/*.file*などに指定することもできますが、ここでは重要ではありません)。

これは完全なコマンドであり、find構文は必要ありません。

  • 「通常の」#の代わりに/を区切り文字として使用して、パターンでそれをエスケープする必要がないようにします。
  • 「ディレクトリ区切り文字ではない」の(貪欲な)グループ、ディレクトリ区切り文字、ファイル名、行末の順にキャプチャします。これにより、最初のキャプチャグループが各ファイルの親ディレクトリになります。
  • ファイル名の最初の部分は、序数の接尾辞を保持するための末尾を除いて、破棄されます。

ファイルがすべて8文字の長さであると想定するよりも、より一般的なアプローチを使用することを選択しましたが、実際の違いは、find構文も、$dir変数を(おそらく安全ではない)正規表現環境。

0