디렉토리에 prefix로 시작하는 여러 파일이 있습니다 ( fgh
예 :
fghfilea
fghfileb
fghfilec
prefix로 시작하도록 모든 이름을 바꾸고 싶습니다 jkl
. 각 파일의 이름을 개별적으로 바꾸는 대신 단일 명령을 수행해야합니까?
디렉토리에 prefix로 시작하는 여러 파일이 있습니다 ( fgh
예 :
fghfilea
fghfileb
fghfilec
prefix로 시작하도록 모든 이름을 바꾸고 싶습니다 jkl
. 각 파일의 이름을 개별적으로 바꾸는 대신 단일 명령을 수행해야합니까?
답변:
몇 가지 방법이 있지만 사용 rename
하는 것이 가장 쉬울 것입니다.
하나의 버전 사용 rename
:
rename 's/^fgh/jkl/' fgh*
다른 버전을 사용하면 rename
( Judy2K의 답변 과 동일 ) :
rename fgh jkl fgh*
플랫폼 설명서 페이지를 확인하여 위 중 어느 것이 적용되는지 확인해야합니다.
rename
다음 구문 보이고있다 unixhelp.ed.ac.uk/CGI/man-cgi?rename하는 것은 다른 일이다
rename
는 Linux 전용 스크립트 또는 유틸리티 인 것 같습니다. 이식성에 관심이 있다면 계속 사용 sed
하고 루프 또는 인라인 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 shell 에서이 예제를 사용하십시오.
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"
여러 가지 방법이 있습니다 (이들 모두가 모든 유닉스 시스템에서 작동하는 것은 아닙니다) :
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에는 가장 일반적인 유닉스 시스템 인 이름 바꾸기가 없습니다.
rename fgh jkl fgh*
ls | perl -ne 'chomp; next unless -e; $o = $_; s/fgh/jkl/; next if -e; rename $o, $_';
Perl을 사용한다고 주장하지만 시스템에 이름을 바꾸지 않은 경우이 몬스터를 사용할 수 있습니다.
그중 일부는 약간 복잡하고 목록이 완전하지는 않지만 거의 모든 유닉스 시스템에서 원하는 것을 찾을 수 있습니다.
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
이 예제에서 모든 발생을 ;
space로 바꾸는 표현식에 주목하십시오 . 이것은 물론 특정 요구에 따라 교체해야합니다.
사용 StringSolver의 어떤 프로세스의 예에 의해 도구 (윈도우 및 리눅스 bash는)
filter fghfilea ok fghreport ok notfghfile notok; mv --all --filter fghfilea jklfilea
먼저 예제를 기반으로 필터를 계산합니다 . 여기서 입력은 파일 이름 및 출력 (ok 및 notok, 임의 문자열)입니다. filter에 --auto 옵션이 있거나이 명령 이후에 단독으로 호출 된 경우 폴더 ok
와 폴더를 작성하고 notok
파일을 각각 해당 폴더 로 푸시합니다.
그런 다음 필터를 사용하여 mv
명령은 반자동 이동 이며 수정 자 --auto를 사용하여 자동으로 변경됩니다. --filter하기 이전 필터 감사를 사용하면,에서 매핑 발견 fghfilea
에를 jklfilea
하고 필터링 된 모든 파일에 적용됩니다.
다른 단선 솔루션
동일한 방법을 사용하는 다른 동등한 방법 (각 줄은 동일 함)을 사용하여 좋아하는 방법을 선택할 수 있습니다.
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
그리고 voilà! 모든 이름 변경은 필터를 사용하여 수행됩니다.
면책 조항 : 나는 학업 목적으로 만든이 작품의 공동 저자입니다. 배쉬 생성 기능도 곧있을 수 있습니다.
Ruby에서이 작업을 수행하는 것이 훨씬 쉬웠습니다. 다음은 두 가지 예입니다.
# 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
이 문제를 해결하는 자체 스크립트를 사용하는 것이 좋습니다. 또한 파일 이름의 인코딩을 변경하고 분음 부호를 미리 작성된 문자로 변환하는 옵션이 있습니다. 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
이것은 regexp를 사용하여 나를 위해 일했습니다.
파일 이름을 다음과 같이 바꾸고 싶었습니다.
file0001.txt -> 1.txt
ofile0002.txt -> 2.txt
f_i_l_e0003.txt -> 3.txt
[az | _] + 0 * ([0-9] +. ) regexp를 사용하십시오. 여기서 ([0-9] +. )는 이름 바꾸기 명령에 사용할 그룹 하위 문자열 입니다.
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
경고하십시오.
찾은 파일의 이름을 .avi로 재귀 적으로 바꾸는 모든 .mkv 파일을 검색하기 위해이 스크립트를 작성했습니다. 니즈에 맞게 사용자 정의 할 수 있습니다. 나중에 무언가를 참조해야 할 경우를 대비하여 파일 경로에서 파일 디렉토리, 확장자, 파일 이름 가져 오기와 같은 다른 것들을 추가했습니다.
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*