
Linuxシステムには「pre_」のような接頭辞付きのファイルセットがあり、それを削除してすべてのファイルの名前を変更したいと思います。これは私が書いたPerlコードです。エラーは発生しませんが、操作はまだ完了していません。
#!/usr/bin/perl -w
my @files = `ls -1 | grep -i \"pre_.*\"`;
foreach $file ( @files )
{
my @names = split(/pre_/, $file);
my $var1 = $names[1];
'mv "$file" "$var1"';
}
答え1
あなたは何も実行しません。一重引用符()内に何かを入れると、''
これは単なる文字列なので、'mv "$file" "$var1"'
コマンドではなく文字列であり、何もしません。文字列自体は真の記述です。このコマンドを実行するには、以下を使用する必要があります。
system "mv", "--", $file, $var1;
(いいえ これによりコマンドインジェクションの脆弱性が発生します。)system("mv '$file' '$var1'")
しかし、必ずしもそうする必要はありません。次perl
の機能をrename()
使用できます。
rename($file, $var1)
次に、実際に解析してはならない出力は次ls
のようになります。とても悪い考えで壊れやすいです。。また、Perl(または他のプログラミング言語)ではまったく必要ありません。その文字列を含む現在のディレクトリ内のすべてのファイルを一致させるにはpre_
(これはすぐにgrep
行うことです。必要はありませんが、grep
これを使用するだけですls -d -- *pre_*
)、次のことができますglob()
。
my @files = glob("*pre_*");
したがって、これらすべてを総合すると次のようになります。
#!/usr/bin/perl -w
use File::Glob qw(:globally :nocase);
my @files = glob("*pre_*");
foreach $file ( @files )
{
my @names = split(/pre_/i, $file);
rename($file, $names[1]);
}
しかし、それは本当に良い考えではありません。同じプレフィックス(たとえば、pre_file1
およびapre_file1
)を持つ2つのファイルがある場合、最初のファイルは2番目のファイルで上書きされます。この例では、file1
コマンドはpre_
その前のすべてのエントリを削除するため、両方のファイルの名前が変更されます。したがって、警告を追加して次のファイルをスキップできます。
#!/usr/bin/perl -w
use File::Glob qw(:globally :nocase);
my @files = glob("*pre_*");
foreach $file ( @files )
{
my @names = split(/pre_/i, $file);
if (-e $names[1]) {
warn "Warning: Not renaming '$file' to '$names[1]' " .
"because '$names[1]' exists.\n";
next;
}
rename($file, $names[1]) or
warn "rename '$file': $!\n";
}
もちろん、これはすべての車輪を再発明することです。直接インストールしてからperl-rename
(Debian、Ubuntuなどで実行する、他のシステムでは、またはapt install rename
)、次のことができます(大文字と小文字を区別しませんが、含まれているファイルのみを探します)。prename
perl-rename
pre_
rename -n 's/.*?pre_//si' ./*
実際の名前を変更せずに実行するジョブのみを印刷します-n
。rename
名前の変更が期待どおりに機能すると確信している場合は、-n
実際にファイル名を変更せずにコマンドを再実行してください。
シェルがここを通りますみんな(非表示)ファイルであり、コードによって名前が変更されていないファイルはrename
無視されます。また、in、inで大文字と小文字を区別しないファイル名のみを渡すようにシェルに指示するか、グローバル設定オプションを使用することもできます。rename
perl
pre_
./~(i)*pre_*
ksh93
./(#i)*pre_*
zsh -o extendedglob
nocaseglob
bash
zsh
yash
./*[pP][rR][eE]_*
答え2
必要なツールがすでに存在していますrename
(配布パネルによって異なりますperl-rename
)prename
。
rename 's/^pre_//' file1 file2 ...
-n
テストの実行とリスト名の変更に使用されます-v
。
rename
注:動作が異なるコマンドと混同しないでくださいutil-linux
。
答え3
...他の名前を変更する代替手段があります(「ホイールを再発明」するよりも)はい...
使用mmv
このように:
$ mmv -n '*_*.ext' '#2.ext'
pre_file_number1.ext -> file_number1.ext
pre_file_number2.ext -> file_number2.ext
pre_file_number3.ext -> file_number3.ext
pre_file_number4.ext -> file_number4.ext
またはZシェル(zsh
) 組み込み関数を使ってzmv
このように:
% autoload zmv
% zmv -n '*.ext' '${f#*_}'
mv -- pre_file_number1.ext file_number1.ext
mv -- pre_file_number2.ext file_number2.ext
mv -- pre_file_number3.ext file_number3.ext
mv -- pre_file_number4.ext file_number4.ext
注:-n
上記のいずれの場合も、安全なテスト実行です。出力が満足であれば削除するか-v
(詳細な説明のために) 実際の名前変更が発生します。