2

すべてのファイル名をキャメル/大文字に変更するプロセスを作成しようとしています。私がそこに着くのに最も近いのはこれです:

perl -i.bak -ple 's/\b([a-z])/\u$1/g;' *.txt # or similar .extension.

これはバックアップファイルを作成しているようです(これが私が望むことを確認したら削除します)。ただし、ファイルの名前を変更する代わりに、ファイル内のテキストの名前を変更します。これを行う簡単な方法はありますか?理論的には、私は少し肛門を保持しているので、さまざまな形式のオフィスドキュメントがいくつかあり、次のようになりたいと考えています。

新しいドキュメント.odt
Roffle.ogg
などなど
ボブキャット.flac
猫犬.avi

これは perl で可能ですか、それとも別の言語/組み合わせに変更する必要がありますか?

また、/foo/foo/documents/foo と同様に、/foo/foo/documents のすべてのファイルの名前が変更されるように、これを再帰的にする方法はありますか?

4

6 に答える 6

9

renameを使用する必要があります。

署名は次のとおりです。


rename OLDNAME,NEWNAME

再帰的にするには、 File::Findと一緒に使用します。


use strict;
use warnings;
use File::Basename;
use File::Find;

#default searches just in current directory
my @directories = (".");

find(\&wanted,  @directories);

sub wanted {
  #renaming goes here
}

次のスニペットは、見つかったすべてのファイルに対して、 want内のコードを実行します。あなたがやりたいことをしたいの中にコードのいくつかを完了する必要があります。

編集: File::Find を使用してこのタスクを達成しようとしましたが、簡単に達成できるとは思いません。次の手順に従うことで成功できます。

  • パラメータがディレクトリの場合は、大文字にしてすべてのファイルを取得します

  • 各ファイルについて、ディレクトリの場合は、このファイルを引数として最初に戻ります

  • ファイルが通常のファイルの場合は、大文字にします

このスクリプトを書いているときに、Perl が邪魔をしました。私はこのスクリプトを ruby​​ で書きました:


require "rubygems"
require "ruby-debug"

# camelcase files

class File
    class << self
        alias :old_rename :rename
    end

    def self.rename(arg1,arg2)
        puts "called with #{arg1} and #{arg2}"
        self.old_rename(arg1,arg2)
    end
end

def capitalize_dir_and_get_files(dir)
    if File.directory?(dir)
        path_c          = dir.split(/\//)
        #base           = path_c[0,path_c.size-1].join("/")
        path_c[-1].capitalize!  
        new_dir_name    = path_c.join("/")
        File.rename(dir,new_dir_name)
        files = Dir.entries(new_dir_name) - [".",".."]
        files.map! {|file| File.join(new_dir_name,file)}
        return files 
    end
    return []
end

def camelize(dir)
    files = capitalize_dir_and_get_files(dir)
    files.each do |file|
        if File.directory?(file)
            camelize(file.clone)
        else
            dir_name    = File.dirname(file)
            file_name   = File.basename(file)
            extname     = File.extname(file)
            file_components = file_name.split(/\s+/)
            file_components.map! {|file_component| file_component.capitalize}           
            new_file_name = File.join(dir_name,file_components.join(" "))
            #if extname != ""
            #   new_file_name += extname
            #end
            File.rename(file,new_file_name)
        end
    end
end

camelize(ARGV[0])

私のPCでスクリプトを試してみましたが、あなたが言及したルールに従って、すべてのディレクトリ、サブディレクトリ、およびファイルを大文字にします。これはあなたが望む動作だと思います。perl バージョンを提供していないことをお詫びします。

于 2009-03-24T15:51:42.170 に答える
5

ほとんどのシステムには rename コマンドがあります ....

NAME rename - 複数のファイルの名前を変更します

rename [ -v ] [ -n ] [ -f ] perlexpr [ files ]

説明 "rename" は、最初の引数として指定された規則に従って、指定されたファイル名の名前を変更します。perlexpr 引数は、指定されたファイル名の少なくとも一部について、Perl の $_ 文字列を変更することが期待される Perl 式です。指定されたファイル名が式によって変更されていない場合、名前は変更されません。コマンドラインでファイル名が指定されていない場合、ファイル名は標準入力を介して読み取られます。

   For example, to rename all files matching "*.bak" to strip the extension, you might say

           rename 's/\.bak$//' *.bak

   To translate uppercase names to lower, you’d use

           rename 'y/A-Z/a-z/' *

オプション -v, --verbose 詳細: 正常にリネームされたファイルの名前を出力します。

   -n, --no-act
           No Action: show what files would have been renamed.

   -f, --force
           Force: overwrite existing files.

著者 ラリー・ウォール

診断 無効な Perl 式を指定すると、構文エラーが発生します。

于 2009-03-25T09:49:38.537 に答える
3

Perl は複数のプラットフォームで問題なく動作するため、FAT (および FAT32 など) ファイルシステムは、ファイル名の大文字と小文字を変更するだけの名前変更を無視することを警告しておきます。これは Windows と Linux に当てはまり、FAT ファイルシステムをサポートする他のプラットフォームにも当てはまります。

したがって、Geo の回答に加えて、ファイル名を実際に変更し (たとえば、最後に文字を追加するなど)、大文字と小文字を区別して目的の名前に戻す必要がある場合があることに注意してください。

NTFS ファイルシステムまたは ext2/3/4 ファイルシステム (または他の UNIX/Linux ファイルシステム) でのみファイルの名前を変更する場合は、おそらくこれについて心配する必要はありません。Mac OSX ファイルシステムがどのように機能するかはわかりませんが、BSD に基づいているため、名前の大文字と小文字を変更するだけでファイルの名前を変更できると思います。

于 2009-03-24T16:00:53.660 に答える
1

もう1つ:

find . -type f -exec perl -e'
  map {
        ( $p, $n, $s ) = m|(.*/)([^/]*)(\.[^.]*)$|;
        $n =~ s/(\w+)/ucfirst($1)/ge;
        rename $_, $p . $n . $s;
      } @ARGV
  ' {} +
于 2009-03-25T16:21:01.793 に答える
1

find コマンドを使用してサブディレクトリを繰り返し、 mv を使用して名前を変更しますが、Perl を利用して名前を正しく変更します。

find /foo/foo/documents -type f \
     -execdir bash -c 'mv "$0" \
                          "$(echo "$0" \
                              | perl -pe "s/\b([[:lower:]])/\u\$1/g; \
                                          s/\.(\w+)$/.\l\$1/;")"' \
              {} \;

不可解ですが、機能します。

于 2009-03-24T20:30:07.023 に答える
0

大文字と小文字を区別するファイルシステム(FAT / NTFS)では、最初にファイルの名前を別の名前に変更してから、大文字と小文字を変更する必要があることに注意してください。「etc.etc」から「Etc.Etc」への直接の名前変更は失敗するか無視されるため、「etc.etc」から「etc.etc〜」、「etc.etc〜」の2つの名前変更を行う必要があります。たとえば、「Etc.Etc」に。

于 2009-03-25T16:42:24.003 に答える