2011-06-02 17 views
1

ディレクトリ名とその下にあるすべてのファイルを別の名前に変更するディレクトリがあります。例えば、私のディレクトリ構造がlinux上の特定の文字列を含むすべてのディレクトリ/ファイルの名前を変更する方法

./mydir_ABC/ 
./mydir_ABC/myfile_ABC.txt 
./mydir_ABC/otherdir_ABC/ 

であると私はそのすべての関連するディレクトリとファイルの一覧を取得するには

find . -type 'f' -name '*ABC*' 
find . -type 'd' -name '*ABC*' 

を使用しています例

./mydir_DEF/ 
./mydir_DEF/myfile_DEF.txt 
./mydir_DEF/otherdir_DEF/ 

のためにそれを作りたいです彼らの名前に私の文字列を入れてください。実際にディレクトリ名とファイル名を変更する別のコマンドにどのようにパイプするのですか? (私はファイルまたはディレクトリが既に存在する場合は上書きできるようにしたい。)

答えて

2

rename(1)コマンドを参照してください。それにはいくつかのバリエーションがありますが、それらはすべて、何らかの正規表現に基づいた何らかの名前の変更をサポートしています。

rename 's%ABC%DEF%g' ... 

それとも、あなたの例のために:私が使用したバージョン(Perlのラクダブック」の初版からのコードに基づく)として使用される

find . -print0 | xargs -0 rename s/ABC/DEF/g 

あるいは、問題を回避するために、あなたは、ディレクトリ構造を横断している間に、パス名は変更して、ディレクトリ名は最初に、その後、(問題のように)ファイルでください:あなたは(行くよう

find . -type d -print0 | xargs -0 rename s/ABC/DEF/g 
find . -type f -print0 | xargs -0 rename s/ABC/DEF/g 

はまだリネームディレクトリに問題がある可能性がありbecaus e ./ABCの名前を./DEFに変更した後は、./ABC/subABC/から./DEF/subDEFに名前を変更することはできません。ディレクトリは現在./DEF/subABCです)。

他のバージョンのrenameでは構文が異なります。マニュアルページを確認してください。ここで


はPerlのラクダブック」の初版由来renameのPerlベースのバージョンです。バージョン管理下に私が持っている最初のバージョンは1992年1月5日の日付を持っています。今日の変更はシェバングライン(ENVを使用して、それが信頼できるものではありませんので、-wを除去し、無-wを補うためにuse warnings;を追加)を更新しました。以前の変更は2008年、1998年、1996年および1992年であった。それは過去19年間であまり変化していません。

#!/usr/bin/env perl 
# 
# @(#)$Id: rename.pl,v 1.8 2011/06/03 22:30:22 jleffler Exp $ 
# 
# Rename files using a Perl substitute or transliterate command 

use strict; 
use warnings; 
use Getopt::Std; 

my(%opts); 
my($usage) = "Usage: $0 [-fnxV] perlexpr [filenames]\n"; 
my($force) = 0; 
my($noexc) = 0; 
my($trace) = 0; 

die $usage unless getopts('fnxV', \%opts); 

if ($opts{V}) 
{ 
    printf "%s\n", q'RENAME Version $Revision: 1.8 $ ($Date: 2011/06/03 22:30:22 $)'; 
    exit 0; 
} 
$force = 1 if ($opts{f}); 
$noexc = 1 if ($opts{n}); 
$trace = 1 if ($opts{x}); 

my($op) = shift; 
die $usage unless defined $op; 

if ([email protected]) { 
    @ARGV = <STDIN>; 
    chop(@ARGV); 
} 

for (@ARGV) 
{ 
    if (-e $_ || -l $_) 
    { 
     my($was) = $_; 
     eval $op; 
     die [email protected] if [email protected]; 
     next if ($was eq $_); 
     if ($force == 0 && -f $_) 
     { 
      print STDERR "rename failed: $was - $_ exists\n"; 
     } 
     else 
     { 
      print "+ $was --> $_\n" if $trace; 
      print STDERR "rename failed: $was - $!\n" 
       unless ($noexc || rename($was, $_)); 
     } 
    } 
    else 
    { 
     print STDERR "$_ - $!\n"; 
    } 
} 
+0

これは特に動作しませんでしたが、私はもっと感謝しています。ディレクトリの名前を変更することもできますか? – Michael

+0

@Michael - 'find'バージョンに 'g'接尾辞を付けるのを忘れました。はい、それはディレクトリの名前を変更することができますが、最初にディレクトリ名を変更してファイル名を変更する方が良いかもしれません。 –

+0

私は同じ名前変更コマンドを使用しているかわかりません。名前を変更するための私のmanページはhttp://linux.die.net/man/1/renameのものと似ています。構文が異なって見えますが、それはあまり強力ではないと思います。あなたの 'rename(1)'は私のディストリビューション(RHEL5)に付属していないと思います。私は 'rename(1)'とそれとは異なる、ubuntuのmanページを見ました。あなたが提案したものにもっと似ています。 – Michael

0

それは常に、これは十分に機能する必要があり、最後の3つの文字があります場合は、私が思うだろう:

mv *abc.* *def.* 
+0

最後の3文字に限定されず、ファイル/ディレクトリ名の任意の場所に指定できます。 – Michael

2
mkdir z; cd z; touch fooabcbar; touch fooABCbar 
find . -type 'f' \(-name '*ABC*' -o -name '*abc*' \) | while read f; do g=`echo "$f" | sed -e 's/abc/def/g' -e 's/ABC/DEF/g'`; echo mv -- "$f" "$g"; done 

限りパス名には改行文字は含まれていません(非常にまれです)。

+1

bashはテキスト置換を持っているので、必要sedはありません: 'グラム= $ {F // ABC/DEF}' –

+0

それは 'ながら私を与え@Seth: – Michael

+0

@michael Syntax.'式:あなたがコピー&ペーストを持っている必要がありますエラー。私はちょうどこれをテストし、それは働いた。私はテストケースで答えを更新します。 –

関連する問題