私は約名前を変更する必要があります。 70,000ファイル。例:sb_606_HBO_DPM_0089000
からsb_606_dpm_0089000
など。
番号の範囲は0089000
から0163022
までです。変更する必要があるのは、名前の最初の部分だけです。すべてのファイルは単一のディレクトリにあり、順番に番号が付けられます(イメージシーケンス)。番号は変更しないでください。
これをbashで試すと、「引数リストが長すぎる」とグリズリングします。
編集:
私は最初に単一のファイルの名前をmv
で変更しようとしました:
mv sb_606_HBO_DPM_0089000.dpx sb_606_dpm_0089000.dpx
次に、範囲の名前を変更しようとしました(先週、ここで大量のファイルを移動する方法を学びましたので、ファイルの名前を変更するために同じ構文が機能すると考えました...)。 I 思考私は次の(またはそれに似た)を試しました:
mv sb_606_HBO_DPM_0{089000..163023}.dpx sb_606_dpm_0{089000..163023}.dpx
1つの方法は、find
を-exec
とともに使用し、+
オプションを使用することです。これは引数リストを作成しますが、リストを必要な数の呼び出しに分割して、最大引数リストを超えずにすべてのファイルを操作します。すべての引数が同じように扱われる場合に適しています。これはrename
の場合ですが、mv
の場合ではありません。
Perl renameのインストールが必要になる場合があります。
Sudo apt install rename
次に、たとえば、次を使用できます。
find . -maxdepth 1 -exec rename -n 's/_HBO_DPM_/_dpm_/' {} +
実際にファイルの名前を変更するには、テスト後に-n
を削除します。
3つの代替案を提案します。それぞれは単純な単一行コマンドですが、主に処理するファイルが同じディレクトリ内の他のファイルと混在している場合に備えて、より複雑な場合のバリアントを提供します。
同じ名前のパッケージ から mmvコマンド を使用します。
mmv '*HBO_DPM*' '#1dpm#2'
引数は文字列として渡されるため、シェルではグロブ展開が行われないことに注意してください。このコマンドは正確に2つの引数を受け取り、対応するファイルを内部的に検索します。ファイル数に厳しい制限はありません。また、上記のコマンドは、最初のグロブに一致するすべてのファイルの名前が変更されることを前提としていることに注意してください。もちろん、もっと具体的にすることは自由です:
mmv 'sb_606_HBO_DPM_*' 'sb_606_dpm_#1'
同じディレクトリに要求された番号範囲外のファイルがある場合、この回答でさらに下に指定された番号のループを使用する方がよい場合があります。ただし、適切なパターンでmmv呼び出しのシーケンスを使用することもできます。
mmv 'sb_606_HBO_DPM_0089*' 'sb_606_dpm_0089#1' # 0089000-0089999
mmv 'sb_606_HBO_DPM_009*' 'sb_606_dpm_009#1' # 0090000-0099999
mmv 'sb_606_HBO_DPM_01[0-5]*' 'sb_606_dpm_01#1#2' # 0100000-0159999
mmv 'sb_606_HBO_DPM_016[0-2]*' 'sb_606_dpm_016#1#2' # 0160000-0162999
mmv 'sb_606_HBO_DPM_01630[01]?' 'sb_606_dpm_01630#1#2' # 0163000-0163019
mmv 'sb_606_HBO_DPM_016302[0-2]' 'sb_606_dpm_016302#1' # 0163020-0163022
何もインストールしないようにする場合、またはこの範囲外の一致を避けるために番号範囲で選択する必要があり、74,023個のコマンド呼び出しを待機する準備ができている場合は、単純なbashループを使用できます。
for i in {0089000..0163022}; do mv sb_606_HBO_DPM_$i sb_606_dpm_$i; done
シーケンスにギャップがないため、これはここで特にうまく機能します。それ以外の場合は、ソースファイルが実際に存在するかどうかを確認することをお勧めします。
for i in {0089000..0163022}; do
test -e sb_606_HBO_DPM_$i && mv sb_606_HBO_DPM_$i sb_606_dpm_$i
done
for ((i=89000; i<=163022; ++i))
とは対照的に、数年前に一部のBashがリリースされて以来、ブレース展開は先行ゼロを処理することに注意してください。実際に私が要求した変更であるため、使用例が表示されてうれしいです。
さらに読む:ブレース展開 Bash情報ページ、特に{x..y[..incr]}
に関する部分。
別のオプションは、問題の整数範囲を単にループするのではなく、適切なグロブをループすることです。このようなもの:
for i in *HBO_DPM*; do mv "$i" "${i/HBO_DPM/dpm}"; done
繰り返しますが、これはファイルごとにmv
呼び出しです。繰り返しますが、ループは要素の長いリストに対して行われますが、リスト全体がサブプロセスへの引数として渡されるのではなく、bashによって内部的に処理されるため、制限は問題を引き起こしません。
さらに読む:Shell Parameter Expansion Bash情報ページで、特に${parameter/pattern/string}
を文書化。
番号範囲を指定したものに制限する場合は、そのためのチェックを追加できます。
for i in sb_606_HBO_DPM_+([0-9]); do
if [[ "${i##*_*(0)}" -ge 89000 ]] && [[ "${i##*_*(0)}" -le 163022 ]]; then
mv "$i" "${i/HBO_DPM/dpm}"
fi
done
ここで${i##pattern}
は、$i
からpattern
に一致する最長のプレフィックスを削除します。その最も長いプレフィックスは、すべて、アンダースコア、ゼロまたはそれ以上のゼロとして定義されます。後者は、拡張された glob pattern である*(0)
として記述されます。これは、設定されている extglob
option に依存します。先頭のゼロを削除することは、数値を基数8ではなく基数10として扱うために重要です。ループ引数の+([0-9])
は、同じ開始文字であるが数字で終わらない.
ARG_MAX
の制限を回避する1つの方法は、bashシェルの組み込みprintf
を使用することです。
printf '%s\0' sb_* | xargs -0 rename -n 's/HBO_DPM/dpm/'
例.
rename -n 's/HBO_DPM/dpm/' sb_*
bash: /usr/bin/rename: Argument list too long
しかし
printf '%s\0' sb_* | xargs -0 rename -n 's/HBO_DPM/dpm/'
rename(sb_606_HBO_DPM_0089000, sb_606_dpm_0089000)
.
.
.
rename(sb_606_HBO_DPM_0163022, sb_606_dpm_0163022)
find . -type f -exec bash -c 'echo $1 ${1/HBO_DPM/dpm}' _ {} \;
./sb_606_HBO_DPM_0089000 ./sb_606_dpm_0089000
find
現在のディレクトリ.
すべてのファイル-type f
に対して、$1
をHBO_DPM
でdmp
に置き換えて、見つかったファイルの名前を変更します 1つずつ-exec ... \;
名前変更を実行するには、echo
をmv
に置き換えます。
あなたはそれをファイルごとに行うことができます(時間がかかる場合があります)
Sudo apt install util-linux # if you don't have it already
for i in *; do rename.ul HBO_DPM dpm "$i"; done
他の回答で使用されるPerl rename
と同様に、rename.ul
にはテスト用の-n
または--no-act
オプションもあります。
次のような小さなpythonスクリプトを作成できます。
import os
for file in os.listdir("."):
os.rename(file, file.replace("HBO_DPM", "dpm"))
これをテキストファイルとしてrename.py
としてファイルが保存されているフォルダーに保存し、そのフォルダーのターミナルを使用して移動します。
python rename.py
オプションを提供しているので、ここにPerlのアプローチがあります。 cd
をターゲットディレクトリに移動して実行します。
Perl -e 'foreach(glob("sb_*")){rename $_, s/_HBO_DPM_/_dpm_/r}'
Perl -e
:-e
で指定されたスクリプトを実行します。foreach(glob){}
:グロブの各結果に対して{ }
にあるものを実行します。glob("sb_*")
:現在のディレクトリ内で、Shell glob sb*
と一致する名前を持つすべてのファイルとディレクトリのリストを返します。rename $_, s/_HBO_DPM_/_dpm_/r
:Perlマジック。 $_
は、繰り返し処理する各要素(foreach
内)を保持する特別な変数です。したがって、ここでは、見つかった各ファイルになります。 s/_HBO_DPM_/_dpm_/
は、最初に出現する_HBO_DPM_
を_dpm_
に置き換えます。デフォルトでは$_
で実行されるため、各ファイル名で実行されます。 /r
は、「この置換をターゲット文字列(ファイル名)のコピーに適用し、変更された文字列を返すことを意味します。rename
は、期待どおりの動作をします。 $_
を_HBO_DPM_
に置き換えて、現在のファイル名(_dpm_
)の名前を変更します。拡張された(そしてより読みやすいスクリプト)と同じことを書くことができます:
#! /usr/bin/env Perl
use strict;
use warnings;
foreach my $fileName (glob("sb_*")){
## Copy the name to a new variable
my $newName = $fileName;
## change the copy. $newName is now the changed version
$newName =~ s/_HBO_DPM_/_dpm_/;
## rename
rename $fileName, $newName;
}
私の親友sed
をパーティーに招待した人は誰もいません。次のfor
ループが目標を達成します。
for i in sb_606_HBO_DPM*; do
mv "$i" "$(echo $i | sed 's/HBO_DPM/dpm/')";
done
このようなジョブには多くのツールがありますが、最も理解しやすいツールを選択してください。これはシンプルで、この目的や他の目的に合わせて簡単に変更できます...
想定している名前の変更の種類によっては、複数行の編集で vidir を使用しても十分な場合があります。
特定のケースでは、テキストエディターですべての行を選択し、いくつかのキーストロークでファイル名の_ "HBO"部分を削除できます。