fgh
たとえば、次のように、prefix で始まるディレクトリに複数のファイルがあります。
fghfilea
fghfileb
fghfilec
それらをすべてprefixで始まる名前に変更したいと思いますjkl
。各ファイルの名前を個別に変更する代わりに、それを行う単一のコマンドはありますか?
fgh
たとえば、次のように、prefix で始まるディレクトリに複数のファイルがあります。
fghfilea
fghfileb
fghfilec
それらをすべてprefixで始まる名前に変更したいと思いますjkl
。各ファイルの名前を個別に変更する代わりに、それを行う単一のコマンドはありますか?
回答:
いくつかの方法がありますが、rename
おそらく最も簡単に使用できます。
の1つのバージョンを使用rename
:
rename 's/^fgh/jkl/' fgh*
別のバージョンの使用rename
(Judy2Kの回答と同じ):
rename fgh jkl fgh*
上記のどれが当てはまるかについては、プラットフォームのマニュアルページを確認してください。
rename
、あなたはunixhelp.ed.ac.uk/CGI/man-cgi?renameの構文を示しています
rename
、Linux固有のスクリプトまたはユーティリティのようです。移植性を気にする場合は、引き続きsed
andループまたはインラインPerlスクリプトを使用してください。
brew install rename
OS Xでは:)
これは方法でsed
あり、mv
一緒に使用して名前を変更できます。
for f in fgh*; do mv "$f" $(echo "$f" | sed 's/^fgh/jkl/g'); done
以下のコメントのとおり、ファイル名にスペースが含まれている場合、ファイルを移動する名前を返すサブ関数を引用符で囲む必要があります。
for f in fgh*; do mv "$f" "$(echo $f | sed 's/^fgh/jkl/g')"; done
for f in fgh*; do mv "$f" "$(echo $f | sed 's/^fgh/jkl/g')"; done
touch fghfilea fghfileb fghfilec fghfile\ d
。@DaveNelsonのコメントを考慮に入れることをお勧めします。
名前変更はすべてのシステムにあるとは限りません。持っていない場合は、bashシェルでこの例のシェルを使用してください
for f in fgh*; do mv "$f" "${f/fgh/xxx}";done
sed
コマンドは必要ありません。これは@nikの答えよりも簡単です。
sh
または一般的に他のシェルには存在しないBash拡張であることをより強調して指摘します。
mmvの使用:
mmv "fgh*" "jkl#1"
;
は、と組み合わせて使用し#1
ます。例:mmv ";fgh*" "#1jkl#2"
これを行うには多くの方法があります(これらのすべてがすべてのunixyシステムで機能するわけではありません)。
ls | cut -c4- | xargs -I§ mv fgh§ jkl§
§は、便利なものに置き換えることができます。あなたもこれを行うことができますfind -exec
が、それは多くのシステムで微妙に異なる動作をするので、私は通常それを避けます
for f in fgh*; do mv "$f" "${f/fgh/jkl}";done
粗野だが効果的
rename 's/^fgh/jkl/' fgh*
かなりきれいですが、BSDには名前の変更がありません。これは、最も一般的なUNIXシステムのafaikです。
rename fgh jkl fgh*
ls | perl -ne 'chomp; next unless -e; $o = $_; s/fgh/jkl/; next if -e; rename $o, $_';
Perlの使用を主張するが、システムに名前の変更がない場合は、このモンスターを使用できます。
それらのいくつかは少し複雑で、リストは完全とはほど遠いですが、ほとんどすべてのUNIXシステムで必要なものが見つかります。
rename fgh jkl fgh*
find
、xargs
およびを使用sed
:
find . -name "fgh*" -type f -print0 | xargs -0 -I {} sh -c 'mv "{}" "$(dirname "{}")/`echo $(basename "{}") | sed 's/^fgh/jkl/g'`"'
@nikのソリューションよりも複雑ですが、ファイルの名前を再帰的に変更できます。たとえば、構造、
.
├── fghdir
│ ├── fdhfilea
│ └── fghfilea
├── fghfile\ e
├── fghfilea
├── fghfileb
├── fghfilec
└── other
├── fghfile\ e
├── fghfilea
├── fghfileb
└── fghfilec
これに変換されます、
.
├── fghdir
│ ├── fdhfilea
│ └── jklfilea
├── jklfile\ e
├── jklfilea
├── jklfileb
├── jklfilec
└── other
├── jklfile\ e
├── jklfilea
├── jklfileb
└── jklfilec
動作させるための鍵xargs
は、xargsからシェルを呼び出すことです。
コマンドラインのGroovyを使用してこれを行う方法を次に示します。
groovy -e 'new File(".").eachFileMatch(~/fgh.*/) {it.renameTo(it.name.replaceFirst("fgh", "jkl"))}'
Solarisでは、次のことを試すことができます。
for file in `find ./ -name "*TextForRename*"`; do
mv -f "$file" "${file/TextForRename/NewText}"
done
for file in $(find)
が、根本的に欠陥があり、引用で修正することはできません。場合はfind
戻り./file name with spaces
ますが取得するfor
上でループを./file
、name
、with
、およびspaces
、ループ内で引用のない量が助けない(あるいは必要になること)します。
このスクリプトは、空白を含む可能性のあるディレクトリ/ファイル名を使用して再帰的に名前を変更するのに役立ちました。
find . -type f -name "*\;*" | while read fname; do
dirname=`dirname "$fname"`
filename=`basename "$fname"`
newname=`echo "$filename" | sed -e "s/;/ /g"`
mv "${dirname}/$filename" "${dirname}/$newname"
done
sed
この例ではのすべての出現箇所;
をスペースで置き換える式に注意してください。もちろん、これは特定のニーズに応じて置き換える必要があります。
例で処理するStringSolverツール(windowsおよびLinux bash)の使用:
filter fghfilea ok fghreport ok notfghfile notok; mv --all --filter fghfilea jklfilea
まず、examplesに基づいてフィルターを計算します。ここで、入力はファイル名と出力です(okおよびnotok、任意の文字列)。filterにオプション--autoがある場合、またはこのコマンドの後に単独で呼び出された場合は、フォルダーok
とフォルダーが作成され、notok
それぞれにファイルがプッシュされます。
次に、フィルターを使用して、mv
コマンドは半自動移動で、修飾子--autoで自動になります。--filterする前のフィルタのおかげを使用して、それからのマッピングを発見fghfilea
するjklfilea
と、すべてのフィルタのファイルにそれを適用します。
その他の1行ソリューション
同じことを行う他の同等の方法(各行は同等)なので、好きな方法を選択できます。
filter fghfilea ok fghreport ok notfghfile notok; mv --filter fghfilea jklfilea; mv
filter fghfilea ok fghreport ok notfghfile notok; auto --all --filter fghfilea "mv fghfilea jklfilea"
# Even better, automatically infers the file name
filter fghfilea ok fghreport ok notfghfile notok; auto --all --filter "mv fghfilea jklfilea"
マルチステップソリューション
コマンドが適切に実行されているかどうかを注意深く確認するには、次のように入力します。
filter fghfilea ok
filter fghfileb ok
filter fghfileb notok
フィルターが適切であると確信したら、最初の移動を実行します。
mv fghfilea jklfilea
テストして前のフィルターを使用する場合は、次のように入力します。
mv --test --filter
変換が希望どおりでない場合(たとえばmv --explain
、何かが間違っていることがわかった場合でも)、入力mv --clear
してファイルの移動を再開するかmv input1 input2
、input1およびinput2が他の例である例を追加できます。
自信がある場合は、次のように入力してください
mv --filter
ほら!名前の変更はすべてフィルターを使用して行われます。
免責事項:私は、学術目的で作成されたこの作品の共著者です。まもなくbashを生成する機能があるかもしれません。
Rubyでこれを行うのは(私のMacでは)はるかに簡単でした。以下に2つの例を示します。
# for your fgh example. renames all files from "fgh..." to "jkl..."
files = Dir['fgh*']
files.each do |f|
f2 = f.gsub('fgh', 'jkl')
system("mv #{f} #{f2}")
end
# renames all files in directory from "021roman.rb" to "021_roman.rb"
files = Dir['*rb'].select {|f| f =~ /^[0-9]{3}[a-zA-Z]+/}
files.each do |f|
f1 = f.clone
f2 = f.insert(3, '_')
system("mv #{f1} #{f2}")
end
大容量ファイルの名前を変更する私のバージョン:
for i in *; do
echo "mv $i $i"
done |
sed -e "s#from_pattern#to_pattern#g” > result1.sh
sh result1.sh
この問題を解決する独自のスクリプトを使用することをお勧めします。また、ファイル名のエンコーディングを変更したり、発音区別記号を合成済み文字に変換したりするオプションもあります。これは、Macからファイルをコピーするときにいつも発生する問題です。
#!/usr/bin/perl
# Copyright (c) 2014 André von Kugland
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
$help_msg =
"rename.pl, a script to rename files in batches, using Perl
expressions to transform their names.
Usage:
rename.pl [options] FILE1 [FILE2 ...]
Where options can be:
-v Verbose.
-vv Very verbose.
--apply Really apply modifications.
-e PERLCODE Execute PERLCODE. (e.g. 's/a/b/g')
--from-charset=CS Source charset. (e.g. \"iso-8859-1\")
--to-charset=CS Destination charset. (e.g. \"utf-8\")
--unicode-normalize=NF Unicode normalization form. (e.g. \"KD\")
--basename Modifies only the last element of the path.
";
use Encode;
use Getopt::Long;
use Unicode::Normalize 'normalize';
use File::Basename;
use I18N::Langinfo qw(langinfo CODESET);
Getopt::Long::Configure ("bundling");
# ----------------------------------------------------------------------------------------------- #
# Our variables. #
# ----------------------------------------------------------------------------------------------- #
my $apply = 0;
my $verbose = 0;
my $help = 0;
my $debug = 0;
my $basename = 0;
my $unicode_normalize = "";
my @scripts;
my $from_charset = "";
my $to_charset = "";
my $codeset = "";
# ----------------------------------------------------------------------------------------------- #
# Get cmdline options. #
# ----------------------------------------------------------------------------------------------- #
$result = GetOptions ("apply" => \$apply,
"verbose|v+" => \$verbose,
"execute|e=s" => \@scripts,
"from-charset=s" => \$from_charset,
"to-charset=s" => \$to_charset,
"unicode-normalize=s" => \$unicode_normalize,
"basename" => \$basename,
"help|h|?" => \$help,
"debug" => \$debug);
# If not going to apply, then be verbose.
if (!$apply && $verbose == 0) {
$verbose = 1;
}
if ((($#scripts == -1)
&& (($from_charset eq "") || ($to_charset eq ""))
&& $unicode_normalize eq "")
|| ($#ARGV == -1) || ($help)) {
print $help_msg;
exit(0);
}
if (($to_charset ne "" && $from_charset eq "")
||($from_charset eq "" && $to_charset ne "")
||($to_charset eq "" && $from_charset eq "" && $unicode_normalize ne "")) {
$codeset = langinfo(CODESET);
$to_charset = $codeset if $from_charset ne "" && $to_charset eq "";
$from_charset = $codeset if $from_charset eq "" && $to_charset ne "";
}
# ----------------------------------------------------------------------------------------------- #
# Composes the filter function using the @scripts array and possibly other options. #
# ----------------------------------------------------------------------------------------------- #
$f = "sub filterfunc() {\n my \$s = shift;\n";
$f .= " my \$d = dirname(\$s);\n my \$s = basename(\$s);\n" if ($basename != 0);
$f .= " for (\$s) {\n";
$f .= " $_;\n" foreach (@scripts); # Get scripts from '-e' opt. #
# Handle charset translation and normalization.
if (($from_charset ne "") && ($to_charset ne "")) {
if ($unicode_normalize eq "") {
$f .= " \$_ = encode(\"$to_charset\", decode(\"$from_charset\", \$_));\n";
} else {
$f .= " \$_ = encode(\"$to_charset\", normalize(\"$unicode_normalize\", decode(\"$from_charset\", \$_)));\n"
}
} elsif (($from_charset ne "") || ($to_charset ne "")) {
die "You can't use `from-charset' nor `to-charset' alone";
} elsif ($unicode_normalize ne "") {
$f .= " \$_ = encode(\"$codeset\", normalize(\"$unicode_normalize\", decode(\"$codeset\", \$_)));\n"
}
$f .= " }\n";
$f .= " \$s = \$d . '/' . \$s;\n" if ($basename != 0);
$f .= " return \$s;\n}\n";
print "Generated function:\n\n$f" if ($debug);
# ----------------------------------------------------------------------------------------------- #
# Evaluates the filter function body, so to define it in our scope. #
# ----------------------------------------------------------------------------------------------- #
eval $f;
# ----------------------------------------------------------------------------------------------- #
# Main loop, which passes names through filters and renames files. #
# ----------------------------------------------------------------------------------------------- #
foreach (@ARGV) {
$old_name = $_;
$new_name = filterfunc($_);
if ($old_name ne $new_name) {
if (!$apply or (rename $old_name, $new_name)) {
print "`$old_name' => `$new_name'\n" if ($verbose);
} else {
print "Cannot rename `$old_name' to `$new_name'.\n";
}
} else {
print "`$old_name' unchanged.\n" if ($verbose > 1);
}
}
stale over time
これは正規表現を使用して私のために働きました:
ファイルの名前を次のように変更したいのですが。
file0001.txt -> 1.txt
ofile0002.txt -> 2.txt
f_i_l_e0003.txt -> 3.txt
[az | _] + 0 *([0-9] +。)正規表現を使用(ここで([0-9] +。)は、renameコマンドで使用するグループのサブストリングです)
ls -1 | awk 'match($0, /[a-z|\_]+0*([0-9]+.*)/, arr) { print arr[0] " " arr[1] }'|xargs -l mv
生成する:
mv file0001.txt 1.txt
mv ofile0002.txt 2.txt
mv f_i_l_e0003.txt 3.txt
もう一つの例:
file001abc.txt -> abc1.txt
ofile0002abcd.txt -> abcd2.txt
ls -1 | awk 'match($0, /[a-z|\_]+0*([0-9]+.*)([a-z]+)/, arr) { print arr[0] " " arr[2] arr[1] }'|xargs -l mv
生成する:
mv file001abc.txt abc1.txt
mv ofile0002abcd.txt abcd2.txt
警告、注意してください。
このスクリプトを作成して、すべての.mkvファイルを検索し、見つかったファイルの名前を.aviに再帰的に変更しました。あなたのニーズに合わせてカスタマイズできます。将来何かを参照する必要がある場合に備えて、ファイルパスからファイルディレクトリ、拡張子、ファイル名を取得するなど、他にもいくつか追加しました。
find . -type f -name "*.mkv" | while read fp; do
fd=$(dirname "${fp}");
fn=$(basename "${fp}");
ext="${fn##*.}";
f="${fn%.*}";
new_fp="${fd}/${f}.avi"
mv -v "$fp" "$new_fp"
done;
実行するための汎用スクリプトsed
ファイルのリストにある式を(組み合わせたsed
ソリューションでrename
解決策を):
#!/bin/sh
e=$1
shift
for f in $*; do
fNew=$(echo "$f" | sed "$e")
mv "$f" "$fNew";
done
スクリプトにsed
式を渡し、次にのバージョンと同じようにファイルのリストを渡して呼び出しますrename
。
script.sh 's/^fgh/jkl/' fgh*