`$0` に置換しながら古い値を保存するにはどうすればよいですか?

`$0` に置換しながら古い値を保存するにはどうすればよいですか?

「m」で始まるすべてのファイルの名前を、最初の文字 (この場合は「m」) を削除した同じ名前に変更しようとしています。

私の戦略は次のとおりです。

  1. すべてのファイルを一覧表示します。ls
  2. 欲しいものをフィルターしてegrep
  3. 不要な文字列を、必要な文字列の次にスペースで区切って生成します。たとえばawkmfoo foo
  4. フィードxargsmv mfoo foo

いくつかの質問:

  • これは良い戦略でしょうか?
  • もっと良いものは何ですか?

ステップ 3 で行き詰まっています。以下は私が問題に取り組んだ方法です。

私は次のディレクトリで作業しています:

$ find .
.
./cat
./mbar
./mbaz
./mfoo

1-2をすぐに取得できます。

$ ls | egrep '^m'
mbar
mbaz
mfoo

ステップ 3 はより困難です。gsub必要な 2 番目の文字列を生成しましたが、「スペースで区切られた元の値と結合する」方法がわかりません。

$ ls | egrep '^m' | awk '{ gsub(/^./, ""); print }'
bar
baz
foo

ステップ 4 は私には意味が通っていますが、ステップ 3 をどのように完了すればよいか分からないため、まだ完了できません。以下は、どのように機能すると思うかの一例です。

$ echo mfoo foo | xargs mv
$ find .
.
./cat
./foo
./mbar
./mbaz

ほぼ解決したと思います。古い値を保存して、gsubed 値の横に印刷する方法を見つける必要があります。次の小さな例を試しましたが、うまくいきません。

$ echo mfoo | awk '
pipe quote> { old = $0 }
pipe quote> { new = gsub(/^./, "") }
pipe quote> { print $old " " $new }'
awk: illegal field $(mfoo), name "old"
 input record number 1, file
 source line number 4
  • $0古い値を保存しながら置換を行うにはどうすればよいですか?
  • なぜこのエラーが発生するのでしょうか?

答え1

これにより、操作全体が処理されます。

for file in m*; do mv "${file}" "${file#m}"; done

それを実行する前に、まずは

for file in m*; do echo mv "${file}" "${file#m}"; done

これは、m*ステップ 1 と 2 に glob を使用し、ステップ 3 に${file#m}( の先頭から “m” を削除します${file}) を使用し、最後にステップ 4 にループを使用します。

AWK に関する質問に答えるには、次のようにします。

echo mfoo | awk '{ print $0, substr($0, 2) }'

AWK 変数は を使用しません$。これはフィールドのみに使用されます。これがエラーの原因です。AWK はこれを$old「 の値に従って番号付けされたフィールドの値old」として理解します。コマンドを 1 つのブロックに配置すると読みやすくなります (同じパターンであると仮定)。スクリプトを修正すると、

echo mfoo | awk '{ old = $0; gsub(/^./, ""); print old, $0 }'

答え2

ls | egrep '^m' | awk '{ x=$0; gsub(/^./, ""); $0 = x " " $0 }1' | xargs -l -t mv

ポジックス-リー実装は次-Lのオプションを介して行われますxargs:

ls | egrep '^m' | awk '{ x=$0; gsub(/^./, ""); $0 = x " " $0 }1' | xargs -L 1 -t mv

ls | egrep '^m' | awk '{ x=$0; gsub(/^./, ""); print x, $0 }' | xargs -L 1 -t mv

何に基づいて私は答えたに関する以前の質問に対してxargs、その学習をこの例で有効に活用することができます。

コードを少し変更しましたawk。関数がそれを上書きするため、元の行 ( $0)が保持されますgsub。次に、古い行と新しい行を組み合わせて、送信先の行を取得し、適切な引数でxargs呼び出してmv名前の変更を実行します。

答え3

より良い戦略は、renameコマンドを使用することです。

このコマンドの正確な構文はディストリビューションに固有のものであることに注意してくださいman。特定のバージョンのディストリビューションのページを参照してください。たとえば、Perl 実装を持つ Ubuntu ではrename、正規表現を使用できます。

rename -nono 's/^m//' m*

注意:-nono実際に名前の変更を実行するにはフラグを削除します。

関連情報