我正在尝试创建一个将我的所有文件名重命名为Camel / Capital Case的进程。我必须得到的最接近的是:
perl -i.bak -ple 's/\b([a-z])/\u$1/g;' *.txt # or similar .extension.
这似乎创建了一个备份文件(当我验证这是我想要的时候我会删除它);但它不是重命名文件,而是重命名文件内的文本。有更简单的方法吗?理论是我有几种不同格式的办公文件,因为我有点肛门保留,并希望它们看起来像这样:
New Document.odt Roffle.ogg Etc.Etc Bob Cat.flac Cat Dog.avi
perl是否可以实现,或者我是否需要更改为其他语言/组合?
另外,无论如何都要使这个递归,这样/ foo / foo / documents重命名了所有文件,/ foo / foo / documents / foo也是如此?
答案 0 :(得分: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
}
以下代码段将针对找到的所有文件执行想要内的代码。您必须完成想要中的一些代码才能执行您想要执行的操作。
编辑:我尝试使用File :: Find完成此任务,我认为你不能轻易实现它。您可以按照以下步骤取得成功:如果参数是dir,请将其大写并获取所有文件
对于每个文件,如果是dir,请以此文件作为参数返回开头
如果文件是常规文件,请将其大写
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])
我在我的电脑上尝试了这个脚本,它按照你提到的规则将所有目录,子目录和文件大写。我认为这是你想要的行为。很抱歉没有提供perl版本。
答案 1 :(得分:5)
大多数系统都有重命名命令....
NAME 重命名 - 重命名多个文件
概要 重命名[-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/' *
OPTIONS -v, - verbose 详细:成功重命名文件的打印名称。
-n, --no-act
No Action: show what files would have been renamed.
-f, --force
Force: overwrite existing files.
AUTHOR 拉里沃尔
DIAGNOSTICS 如果您提供无效的Perl表达式,则会出现语法错误。
答案 2 :(得分:3)
由于Perl在多个平台上运行得很好,让我警告您FAT(和FAT32等)文件系统将忽略仅更改文件名大小写的重命名。在Windows和Linux下都是如此,对于支持FAT文件系统的其他平台可能也是如此。
因此,除了Geo's answer之外,请注意您可能必须实际更改文件名(例如,通过在末尾添加字符),然后使用正确的名称将其更改回所需的名称情况下。
如果您只重命名NTFS文件系统上的文件或仅重命名ext2 / 3/4文件系统(或其他UNIX / Linux文件系统),那么您可能不需要担心这一点。我不知道Mac OSX文件系统是如何工作的,但由于它基于BSD,我认为它只允许你通过更改名称的大小写来重命名文件。
答案 3 :(得分: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/;")"' \
{} \;
神秘,但它有效。
答案 4 :(得分:1)
另一个:
find . -type f -exec perl -e'
map {
( $p, $n, $s ) = m|(.*/)([^/]*)(\.[^.]*)$|;
$n =~ s/(\w+)/ucfirst($1)/ge;
rename $_, $p . $n . $s;
} @ARGV
' {} +
答案 5 :(得分:0)
请记住,在记住文件系统(FAT / NTFS)的情况下,您需要先将文件重命名为其他内容,然后再更改为大小写。从“etc.etc”到“Etc.Etc”的直接重命名将失败或被忽略,因此您需要进行两次重命名:“etc.etc”到“etc.etc~”然后“etc.etc~”以“Etc.Etc”为例。