ファイルの内容、ファイル名、ディレクトリ名、許可されたスペースの「大規模置換」のためのBash機能

ファイルの内容、ファイル名、ディレクトリ名、許可されたスペースの「大規模置換」のためのBash機能

私のUbuntuシステムでは、ファイルの内容、ファイル名、ディレクトリ名を「ほとんど置き換える」ことがよくあります。たとえば、ソースコードを別のアプリケーションのテンプレートにコピーする場合です。

~/.bashrc動作しますが、検索または置換文字列にスペースが含まれていると失敗する関数を設定しました。私はこれが原因だと信じていますsedこのコマンドはスクリプトでスペースを許可しません。CDパスにスペースが含まれている場合、パス変数の変更も失敗します。

パラメータは、($ 1)ディレクトリ、($ 2)検索テキスト、($ 3)代替テキストです。

すべてのパラメータにスペースが含まれるようにこのスクリプトを改善できますか?

deepreplace() {


    if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]
    then
        echo "A parameter is missing"
    else

        cd $1

        vfind=$2
        vreplace=$3 

        # Replace the string in file

        find . -type f -exec sed -i "s/$vfind/$vreplace/g" {} +

        # Replace the string in file names, then directories


        find . -type d -name "*$vfind*" | while read f; do mv $f $(echo $f | sed "s/$vfind/$vreplace/g"); done
        find . -type f -name "*$vfind*" | while read f; do mv $f $(echo $f | sed "s/$vfind/$vreplace/g"); done
    fi
}

答え1

コメントで述べたように、純粋なbashソリューションは私のユースケースには適していないと確信しています。

私はNode.js / npmに依存するコマンドを選択しました(NodeはUnixではなく(Windows / Mac)を含む私が作業している環境で非常に一般的だからです)。

2つのnpmパッケージによって異なります名前変更そして変える

これらのライブラリを使用すると、正規表現やその他の高度な名前変更/交換シナリオをサポートするという利点があります。

Node.js/npmをインストールした後:

# Globally install the required packages (this prevents npx from trying to install in current directory if they do not already exist)

$ npm install -g renamer
$ npm install -g replace

# Set variables (dir, find, replace) for directory, find and replace strings, then run change directory, rename and replace, before reverting to original directory.
# npx is not strictly required, but have included to prevent collisions with command names on the PATH.

$ dir="./example_dir" && 
   find="example_find" && 
     replace="example_replace" && 
       cd "$dir" && 
        npx renamer --find "$find" --replace "$replace" "**" && 
            npx replace "$find" "$replace" . -r 
                && cd -

同等の.bashrc関数は次のとおりです。

renamereplace() {

    # Install global packages if not installed

    npm list -g renamer || npm install -g renamer
    npm list -g replace || npm install -g replace

    # Alias positional arguments

    dir="$1"
    find="$2"
    replace="$3" 

    # Change to replace directory

    cd "$dir"

    # Rename in directory and file names

    npx renamer --find "$find" --replace "$replace" "**" 

    # Replace in file contents

    npx replace "$find" "$replace" . -r 

    # Revert current directory

    cd -
}

以下から呼び出すことができます。

$ renamereplace "./example_dir" "example_find" "example_replace"

注意:データの損失を防ぐには、a)このスクリプトを理解し、b)このコマンドが実行されるディレクトリを確認し、c)上記のコマンドを実行する前に、すべての重要なデータをバックアップしていることを確認してください。

答え2

あなたの関数はあなたが望むほとんどすべてのことを行います。変数と置換項目の周りに引用符がたくさんないため、ファイル名のスペースに抵抗しません。

  • 変数:「$1」、「$2」、「$f」など
  • 置換: "$(...)"

最初のロータッチレビューは次のとおりです。

deepreplace() {
  if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]
  then
      echo "A parameter is missing"
  else
    cd "$1" # quote missing
    vfind="$2" # quote missing
    vreplace="$3" # quote missing
    # Replace the string in file contents
    find . -type f -exec sed -i "s/$vfind/$vreplace/g" {} +
    # Replace the string in directory names
    find . -type d -name "*$vfind*" |
    while read d ; do
      mv "$d" "$(echo "$d" | sed "s/$vfind/$vreplace/g")"
    done
    # Replace the string in file names
    find . -type f -name "*$vfind*" |
    while read f; do
      mv "$f" "$(echo "$f" | sed "s/$vfind/$vreplace/g")"
    done
  fi
}

次の改善点:

  • $(echo $v | sed s/x/y/g)組み込みの例を使用する代わりに${v//x/y}
    : mv "$f" "${f//$vfind/$vreplace}"
  • ディレクトリレベルの上のパスを置き換えようとすると問題が発生します。そのため、ファイルを検索してディレクトリを検索するのではなく、まずディレクトリをターゲットとして指定し、次にファイルをターゲットとして指定します。
  • find3回実行しても役に立ちません。

新しい純粋なbashアプローチは次のとおりです。

    find . | while read p ; do
      ddir="$(dirname "${p//$vfind/$vreplace}")"
      obas="$(basename "$p")"
      nbas="${obas//$vfind/$vreplace}"
      # if object rename
      [[ $obas != $nbas ]] && mv "$ddir/$obas" "$ddir/$nbas"
      # if object is file, edit
      [ -f "$ddir/$nbas" ] && sed -i "s/$vfind/$vreplace/g" "$ddir/$nbas"
    done
  • find自然な出力順序は、ディレクトリが常にサブディレクトリの前に名前が変更されるのと同じであるため、デフォルトの名前要素のみを名前変更するのは安全です。
  • すべての名前にスペースを安全に含めることができます。
  • 1人だけがfindより低いコストで仕事をします。
  • 依存関係をjsに保存します。

関連情報