5

現在のディレクトリ内のファイルの名前を一括で変更し、ファイル名の末尾から特定の文字列を削除したいと考えています。

サンプル:

foo-bar-(ab-4529111094).txt
foo-bar-foo-bar-(ab-189534).txt
foo-bar-foo-bar-bar-(ab-24937932201).txt

出力は次のようになります。

foo-bar.txt
foo-bar-foo-bar.txt
foo-bar-foo-bar-bar.txt

-(ab-2492201)数字の長さが異なる可能性があることを知って、各ファイル名の末尾にある文字列を削除したいと思います。

Perl正規表現はモジュールよりも優先され、ユーティリティを使用せず、bashの場合はonelinerコマンドが強く推奨されます。

Linux上のPerlとBashShellの両方でそれを達成する方法は?両方の解決策を知りたい。

4

7 に答える 7

7

試す:

$ rename 's/-\(ab-\d+\)(?=\.txt$)//' *.txt

renamePerlで書かれたコマンドがあります。その最初の引数は、ファイル名を変換する方法を説明するPerlコードです。s///独自のPerlプログラムまたはワンライナーで同じコマンドを使用できます。

それでもうまくいかない場合は、 ;prenameの代わりに試してください。rename一部のシステムには、Perlベースではない別のrenameコマンドがインストールされています。この場合、Perlコマンドはと呼ばれることがありますprename

于 2013-01-09T22:26:52.400 に答える
4

bashでは、次のように書くことができます。

for file in *-\(ab-[0-9]*\)*; do
    newfile="${file/-(ab-[0-9]*)/}"
    mv "$file" "$newfile"
done
于 2013-01-09T22:28:27.080 に答える
3

Perl正規表現を使用してファイルの名前を変更する

、、、findおよびを使用するperlxargs、このワンライナーを使用できます

find . -type f | perl -pe 'print $_; s/input/output/' | xargs -n2 mv

電話をかけなくても結果mv

OldName NewName
OldName NewName
OldName NewName

それはどのように機能しますか?

  1. find . -type fファイルパスを出力します(またはファイル名...ここで正規表現によって処理されるものを制御します!)
  2. -p正規表現で処理されるファイルパスを出力し、-eインラインスクリプトを実行します
  3. print $_元のファイル名を最初に出力します(に関係なく-p
  4. -n21行に2つの要素を出力します
  5. mv前の行の入力を取得します
于 2019-02-24T17:36:44.510 に答える
2

現在のディレクトリの下で言うとき、あなたは現在のディレクトリ、または現在のディレクトリとその子孫の中または下のどこかを意味しますか?

File::Find後者を行う簡単な方法であり、コアモジュールであるため、インストールする必要はありません。そのようです:

use strict;
use warnings;

use autodie;

use File::Find;

find(\&rename, '.');

sub rename {
  return unless -f;
  my $newname = $_;
  return unless $newname =~ s/-\(ab-[0-9]+\)(\.txt)$/$1/i;
  print "rename $_, $newname\n";
}

アップデート

このプログラムは、現在のディレクトリ内でのみ、指定されたファイル名パターンですべてのファイルの名前を変更します。

最初のopenループは、名前を変更するためのサンプルファイルを作成するためだけにあることに注意してください。

use strict;
use warnings;

use autodie;

open my $fh, '>', $_ for qw(
  foo-bar-(ab-4529111094).txt
  foo-bar-foo-bar-(ab-189534).txt
  foo-bar-foo-bar-bar-(ab-24937932201).txt
);

for (glob '*.txt') {
  next unless -f;
  my $newname = $_;
  next unless $newname =~ s/-\(ab-[0-9]+\)(\.txt)$/$1/i;
  print "rename $_, $newname\n";
  rename $_, $newname;
}

出力

rename foo-bar-(ab-4529111094).txt, foo-bar.txt
rename foo-bar-foo-bar-(ab-189534).txt, foo-bar-foo-bar.txt
rename foo-bar-foo-bar-bar-(ab-24937932201).txt, foo-bar-foo-bar-bar.txt
于 2013-01-09T22:38:20.930 に答える
1

よりシンプルで短い(より良い?:))rename正規表現:

rename 's@-\(.*?\)@@' foo*.txt
于 2013-01-09T22:29:18.763 に答える
1

これをチェックして:

ls -1 | nawk '/foo-bar-/{old=$0;gsub(/-\(.*\)/,"",$0);system("mv \""old"\" "$0)}'

> ls -1 foo*
foo-bar-(ab-4529111094).txt
foo-bar-foo-bar-(ab-189534).txt
foo-bar-foo-bar-bar-(ab-24937932201).txt

> ls -1 | nawk '/foo-bar-/{old=$0;gsub(/-\(.*\)/,"",$0);system("mv \""old"\" "$0)}'

> ls -1 foo*
foo-bar-foo-bar-bar.txt
foo-bar-foo-bar.txt
foo-bar.txt
> 

詳細な説明については、こちらを確認してください

于 2013-01-10T05:53:22.977 に答える
0

perlだけを使用する別の方法:

perl -E'for (<*.*>){ ($new = $_) =~ s/(^.+?)(-\(.+)(\..*$)/$1$3/; say  $_." -> ".$new}'

say ...テストに最適です。rename $_,$newまたはに置き換えるだけですrename($_,$new)

  1. <*.*>現在のディレクトリ内のすべてのファイルを読み取ります
  2. ($new = $_) =~次の置換をに保存し、そのまま残し$newます$_
  3. (^.+?)この試合を$1で保存し、最初から欲張りでない試合を...
  4. (-\(.+)シーケンス「-(... anything ...」が見つかりました。(この一致は$ 2に保存されます)
  5. (\..*$)最後の「。」からすべてを保存します。(ピリオド)行の終わり($)の前で、行の終わりまで->$3に
  6. 一致をから生成された文字列に置き換えます$1$3

(特定のディレクトリに対しても実行できます。perl -E'for (</tmp/my/directory/*.*>){ .....

于 2019-08-08T07:44:47.567 に答える