ファイル名のどこにでも数字を入力してファイル名を変更するには?

ファイル名のどこにでも数字を入力してファイル名を変更するには?

Deepin(Debianベース)システムには、次のビデオファイルを含むディレクトリがあります。

SL Benfica - Match 1 vs FC Porto.mp4
SL Benfica - Match 2 vs FC Porto.mp4
...
SL Benfica - Match 20 vs FC Porto.mp4
...
SL Benfica - Match 100 vs FC Porto.mp4
SL Benfica - Match 101 vs FC Porto.mp4

途中の数字の前にゼロを追加して、次のように並べ替えたいと思います。

SL Benfica - Match 001 vs FC Porto.mp4
SL Benfica - Match 002 vs FC Porto.mp4
...
SL Benfica - Match 020 vs FC Porto.mp4
...
SL Benfica - Match 100 vs FC Porto.mp4
SL Benfica - Match 101 vs FC Porto.mp4

モードに依存しない一般的なコマンドを探しています。 5と20のような数字を検索して、ファイル名の任意の場所やファイル名の終わりまたは先頭から005と020に変更します。

答え1

利用可能ですperl-rename(Debianベースのシステムにインストールできる必要がありますsudo apt install rename)。次のファイルを入力として使用します。

$ ls -1
'anotherFile.m4a'    
'file 1 with 12 many 100 numbers 3.mp4'
'SL Benfica - Match 101 vs FC Porto.mp4'
'SL Benfica - Match 20 vs FC Porto.mp4'
'SL Benfica - Match 2 vs FC Porto.mp4'

以下を実行できます。

rename 's/(\d+)(?=.*\.)/sprintf("%03d",$1)/eg' *

これにより、名前が次のように変更されます。

'anotherFile.m4a'
'file 001 with 012 many 100 numbers 003.mp4'
'SL Benfica - Match 002 vs FC Porto.mp4'
'SL Benfica - Match 020 vs FC Porto.mp4'
'SL Benfica - Match 101 vs FC Porto.mp4'

どのよう100に変更されずに残りがいっぱいになるかを確認してください。また、4の.m4a合計はmp4影響を受けません。

重要-n:ファイル名が実際に変更される前に何が起こるかを確認するには、まずコマンドを実行します。

rename -n 's/(\d+)(?=.*\.)/sprintf("%03d",$1)/eg' *

\d+1つ.以上の数字()の前に1つ以上の数字()を見つける正規表現?=.*\.。これは、内線番号の番号が変更されるのを防ぐためです。ただし、ファイル名に拡張子がない場合は機能しません。このようなファイルがある場合は、以下を使用してすべての数字を入力してください。

rename 's/(\d+)/sprintf("%03d",$1)/eg' *

は代替演算子で、でs/old/new/置き換えられます。ここでは括弧内にあるので、一致するものは何でもあります。oldnew(\d+)キャプチャされます$1これにより、交換品の右側で使用できます。したがって、数字をゼロで埋められた数字で置き換えます(ゼロで埋められた数字は、長さが3になるまでsprintf("%03d", $number)印刷されます)。$number最後に、このフラグをe使用すると、式(ここでsprintf)を使用gして代替項目をグローバルに作成して、入力行(ファイル名)のすべての一致に適用できます。

番号に3つ以上のゼロが追加されている場合は、3-0パディングに切り捨てられます。だからfile 00000001.mp3それはなりますfile 001.mp3

答え2

そしてzsh

autoload -Uz zmv # best in ~/.zshrc
zmv -n '(*).mp4' '${1//(#m)<->/${(l[3][0])MATCH}}.mp4'

満足すれば削除-n(テスト実行)します。

  • zmvzsh glob パターンに従ってファイル名を変更します。これ(*).mp4はで終わるファイル名と一致し、.mp4前の部分.mp4は次のとおりです。キャプチャされますだから$1代用として使えます。
  • ${1//pattern/replacement}:ksh演算子は、引数(ここで$1)を拡張すると置換を実行します。
  • これはzshモードpatternです。置換など、一致するテキストを使用できるようにすることは、数値一致演算子の最も単純な形式で、1つ以上の10進数シーケンスと一致します。と同じです。(#m)<->extendedglob(#m)$MATCH<-><x-y>[0-9]##
  • ${(l[3][0])param}引数拡張フラグを使用して、l[length][padstring]ゼロから長さ3までの拡張を左に塗りつぶします$MATCH(数字も長さ3に切り捨てます)。

少し複雑になりますが、切り捨てを防ぐことが可能です。

zmv -n '(*).mp4' '${1//(#m)<->/${(l[$#MATCH > 3 ? $#MATCH : 3][0])MATCH}}.mp4'

パディング+長さを3に切り捨てるのではなく、最大3の長さとパディングする文字列の長さまでパディング+切り捨てます。または、max()自動ロード可能な関数で数学関数を使用することもできますzmathfunc

autoload -Uz zmv zmathfunc; zmathfunc
zmv -n '(*).mp4' '${1//(#m)<->/${(l[max(3, $#MATCH)][0])MATCH}}.mp4'

答え3

GNU sedを使用すると、次のことができます(拡張なしでも):

sed -E \
-e 'h;s/(.*)(\.[^.]*$)/\2/;ta;z;:a;x;s//\1/' \
-e 's/([0-9]{1,})/\n000\1\n/g' \
-e 's/\n[0-9]*([0-9]{3})\n/\1/g' \
-e 'G;s/\n//g' file

ループはなく、正規表現のみが使用されます。

最初の正規表現は一致します

  • 'h;s/(.*)(\.[^.]*$)/\2/;ta;z;:a;x;s//\1/'拡張をスケジュールされたスペース(存在する場合)に配置します。残りはパターン空間に残してください。
  • 's/([0-9]{1,})/\n000\1\n/g'各数値ストリームを別々の行に配置し、その前に3つのゼロを追加します。

前にゼロがあり、独自の行になるように変更する各番号を展開してから、次の操作を行います。

  • 's/\n[0-9]*([0-9]{3})\n/\1/g'各数値行から最後の3桁を抽出します。
  • 'G;s/\n//'起動時にキャプチャされた拡張機能を再接続します。

ソースリストが次の場合:

➤ cat file
1- 23.m2
ATestFile.mp4
SomeFile.m4a
AFileWithNumbers23inside.mp4
File 1 with 12 some 100 numbers 3.mp4
SL Benfica - Match 1 vs FC Porto.mp4
SL Benfica - Match 2 vs FC Porto.mp4
SL Benfica - Match 20 vs FC Porto.mp4
SL Benfica - Match 101 vs FC Porto.mp4

結果は次のとおりです。

001- 023.m2
ATestFile.mp4
SomeFile.m4a
AFileWithNumbers023inside.mp4
File 001 with 012 some 100 numbers 003.mp4
SL Benfica - Match 001 vs FC Porto.mp4
SL Benfica - Match 002 vs FC Porto.mp4
SL Benfica - Match 020 vs FC Porto.mp4
SL Benfica - Match 101 vs FC Porto.mp4

したがって、ファイル名を変更するには(ファイル名に改行文字を含めないでください。拡張子の後にドットを付ける必要があります):

#!/bin/bash

for old in *; do
    new=$(  printf '%s\n' "$old" | 
                sed -E \
                    -e 'h;s/(.*)(\.[^.]*$)/\2/;ta;z;:a;x;s//\1/' \
                    -e 's/([0-9]{1,})/\n000\1\n/g' \
                    -e 's/\n[0-9]*([0-9]{3})\n/\1/g' \
                    -e 'G;s/\n//'
         );
    if [[ ! -f $new ]]; then
        echo \
            mv "$old" "$new";
    fi
done

スクリプトが満足のいくものであれば、削除してecho実際にファイルを変更してください。

答え4

この試み

$ ls SL*mp4 | awk -v mvCmd='mv "%s" "%s"\n' '{ old=$0; $5=sprintf("%3.3d",$5); printf mvCmd,old,$0 }'

新しいファイル名が正しい場合は、コマンドを再実行して出力をbashなどのシェルにパイプします。

このコマンドは元のファイル名(以前)を保存し、5番目の列($ 5)をprintfの列の1つ(3つの数字、小数点なし、0で始まる)に変更し、古い名前と新しい名前の周りの引用符を使用します。 mvを印刷します(置き換えられた命名)。 )コマンド。

awkにはデフォルトでファイル名変更コマンドがないため、出力をbashにパイプする必要があります。

関連情報