Làm thế nào để đổi tên với tiền tố / hậu tố?


95

Làm cách nào để làm mv original.filename new.original.filenamemà không cần nhập lại tên tệp gốc?

Tôi sẽ tưởng tượng có thể làm điều gì đó tương tự mv -p=new. original.filenamehoặc có lẽ mv original.filename new.~hoặc bất cứ điều gì - nhưng tôi không thể thấy bất cứ điều gì như thế này sau khi xem man mv/ info mvtrang.

Tất nhiên, tôi có thể viết một tập lệnh shell để làm điều này, nhưng không có lệnh / cờ hiện có cho nó?

Câu trả lời:


122

Trong Bash và zsh, bạn có thể làm điều này với Brace Expansion . Điều này chỉ đơn giản là mở rộng danh sách các mục trong niềng răng. Ví dụ:

# echo {vanilla,chocolate,strawberry}-ice-cream
vanilla-ice-cream chocolate-ice-cream strawberry-ice-cream

Vì vậy, bạn có thể thực hiện đổi tên của mình như sau:

mv {,new.}original.filename

vì điều này mở rộng thành:

mv original.filename new.original.filename

Cảm ơn, đây có vẻ là giải pháp tốt nhất - cũng hoạt động với ksh.
Peter Boughton 16/10/08

29
Điều này không làm được với các thẻ hoang dã. Nghĩa là, trong thư mục chứa các tên tệp a, b, c, sử dụng "echo {, new.} *" Tạo ra danh sách "abc new. *" (Vì việc tạo tên tệp thông qua mở rộng dấu ngoặc nhọn xảy ra trước khi mở rộng các ký tự đại diện - ít nhất bằng suy luận).
Jonathan Leffler 16/10/08

Kể từ nhiều tháng tôi đang tìm kiếm một giải pháp như vậy chỉ sử dụng chức năng shell cơ bản ... Tôi sẽ không bao giờ nghĩ ra một cái gì đó đơn giản như vậy, cảm ơn rất nhiều!
flonk

Cảm ơn bạn đã tham khảo Brace Expansion :-) chính xác những gì tôi đang tìm kiếm!
Pim Hazebroek

1
Tôi thích ví dụ. Tôi đang cảm thấy có tâm trạng để đến Baskin Robbins trong giờ nghỉ trưa.
Sridhar Sarnobat

156

Bạn có thể sử dụng rename(1)lệnh:

rename 's/(.*)$/new.$1/' original.filename

Chỉnh sửa: Nếu renamekhông có sẵn và bạn phải đổi tên nhiều hơn một tệp, kịch bản shell thực sự có thể ngắn và đơn giản cho việc này. Ví dụ, để đổi tên tất cả *.jpgthành prefix_*.jpgtrong thư mục hiện tại:

for filename in *.jpg; do mv "$filename" "prefix_$filename"; done;

Đã cài đặt graphite vào cuối tuần này và họ có một bước về cơ bản là ("sao chép tất cả các tệp * .example vào thư mục conf, xóa hậu tố ví dụ"). Thực sự lười biếng về phía họ, nhưng rename 's/(.*).example/$1/' *.exampleđã cứu tôi khỏi sự tẻ nhạt.
Conrad.Dean

2
Đây là câu trả lời tốt nhất cho đến nay.
lifeisfoo

Tôi không nghĩ bạn cần cái đầu tiên $trong trường hợp này. Vì vậy, chỉ's/(.*)/new.$1/'
khôn ngoan

1
renamelệnh không hoạt động trên máy RHEL 6 của tôi. Có bất kỳ phiên bản nào khác nhau của lệnh này không? Công for ... doneviệc cho tôi.
robsch

25

Bạn có thể đổi tên nhiều tệp tương thích với unix (sử dụng ký tự đại diện) bằng cách tạo vòng lặp for:

for file in *; do
  mv $file new.${file%%}
done

7
Sự khác biệt giữa điều này và những gì Simon Lehmann đã trả lời ?
Peter Boughton

4
Điều này hoạt động tuyệt vời. Bạn ${file%%}làm gì? Có vẻ như chỉ đơn giản là $ {file}
Sidmitra

Tôi cũng rất tò mò về $ {file %%}
Lucas Bustamante

10

Tôi đã thấy mọi người đề cập đến một renamelệnh, nhưng nó không thường xuyên có sẵn trên các hệ thống Unix (trái ngược với các hệ thống Linux, chẳng hạn, hoặc Cygwin - trên cả hai, đổi tên là một tệp thực thi chứ không phải là một tập lệnh). Phiên bản đó renamecó một chức năng khá hạn chế:

rename from to file ...

Nó thay thế phần từ của tên tệp bằng đến và ví dụ được đưa ra trong trang người đàn ông là:

rename foo foo0 foo? foo??

Thao tác này đổi tên foo1 thành foo01 và foo10 thành foo010, v.v.

Tôi sử dụng một tập lệnh Perl có tên rename, mà ban đầu tôi đã đào ra từ cuốn sách Camel xuất bản đầu tiên, vào khoảng năm 1992, và sau đó mở rộng, để đổi tên tệp.

#!/bin/perl -w
#
# @(#)$Id: rename.pl,v 1.7 2008/02/16 07:53:08 jleffler Exp $
#
# Rename files using a Perl substitute or transliterate command

use strict;
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.7 $ ($Date: 2008/02/16 07:53:08 $)';
    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 (!@ARGV) {
    @ARGV = <STDIN>;
    chop(@ARGV);
}

for (@ARGV)
{
    if (-e $_ || -l $_)
    {
        my($was) = $_;
        eval $op;
        die $@ if $@;
        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";
    }
}

Điều này cho phép bạn viết bất kỳ lệnh thay thế Perl hoặc chuyển ngữ nào để ánh xạ tên tệp. Trong ví dụ cụ thể được yêu cầu, bạn sẽ sử dụng:

rename 's/^/new./' original.filename

Cảm ơn, nếu tôi có thể chấp nhận câu trả lời thứ hai, đây sẽ là nó. Tôi muốn một lệnh chuẩn như một thứ gì đó sẽ hoạt động trên bất cứ thứ gì tôi có thể sử dụng, nhưng tôi có thể đặt tập lệnh này trên các máy tôi thường xuyên sử dụng và nó vẫn sẽ hữu ích.
Peter Boughton 16/10/08

James Wong nhấn mạnh rằng cho Arch Linux, bạn chỉ có thể tải về và cài đặt script này qua pacmansử dụng: pacman -Sy perl-rename. Sau đó, thêm một bí danh để nó trong bashrc của bạn:alias rename='perl-rename'
Jonathan Leffler

làm gì nếu "từ" hay "thành" là chuỗi rỗng, tức là bạn muốn append một cái gì đó cho mỗi tên tập tin hoặc loại bỏ một cái gì đó hoàn toàn
Troyseph

1
@Troyseph - để thêm '.htmlvào tên tệp, sử dụng 's/$/.html/'- để xóa tmpkhỏi mọi nơi trong tên tệp, sử dụng 's/tmp//g'(tìm tmpvà thay thế không có gì ở mọi nơi).
Jonathan Leffler

4

Cách dễ nhất để đổi tên hàng loạt tệp trong thư mục là:

ls | xargs -I fileName mv fileName fileName.suffix

2

Nếu nó mở cho một sửa đổi, bạn có thể sử dụng hậu tố thay vì tiền tố. Sau đó, bạn có thể sử dụng tab-hoàn thành để lấy tên tệp gốc và thêm hậu tố.

Nếu không, không, đây không phải là thứ được lệnh mv hỗ trợ. Tuy nhiên, một tập lệnh shell đơn giản có thể đối phó được.


Thường thì tôi muốn cả hai, nhưng chủ yếu là tiền tố - như bạn nói, việc hoàn thành tab có thể xử lý các hậu tố.
Peter Boughton 16/10/08

1

Trong trường hợp của tôi, tôi có một nhóm tệp cần được đổi tên trước khi tôi có thể làm việc với chúng. Mỗi tệp có vai trò riêng trong nhóm và có mẫu riêng.

Kết quả là tôi có một danh sách các lệnh đổi tên như sau:

f=`ls *canctn[0-9]*`   ;  mv $f  CNLC.$f
f=`ls *acustb[0-9]*`   ;  mv $f  CATB.$f
f=`ls *accusgtb[0-9]*` ;  mv $f  CATB.$f
f=`ls *acus[0-9]*`     ;  mv $f  CAUS.$f

Hãy thử cái này cũng được:

f=MyFileName; mv $f {pref1,pref2}$f{suf1,suf2}

Điều này sẽ tạo ra tất cả các kết hợp có tiền tố và hậu tố:

pref1.MyFileName.suf1
...
pref2.MyFileName.suf2

Một cách khác để giải quyết vấn đề tương tự là tạo mảng ánh xạ và thêm tiền tố corespondent cho mỗi loại tệp như hình dưới đây:

#!/bin/bash
unset masks
typeset -A masks
masks[ip[0-9]]=ip
masks[iaf_usg[0-9]]=ip_usg
masks[ipusg[0-9]]=ip_usg
...
for fileMask in ${!masks[*]}; 
do  
registryEntry="${masks[$fileMask]}";
fileName=*${fileMask}*
[ -e ${fileName} ] &&  mv ${fileName} ${registryEntry}.${fileName}  
done

1

Đổi tên hàng loạt tập tin bash script

#!/bin/bash
# USAGE: cd FILESDIRECTORY; RENAMERFILEPATH/MultipleFileRenamer.sh FILENAMEPREFIX INITNUMBER
# USAGE EXAMPLE: cd PHOTOS; /home/Desktop/MultipleFileRenamer.sh 2016_
# VERSION: 2016.03.05.
# COPYRIGHT: Harkály Gergő | mangoRDI (https://wwww.mangordi.com/) 

# check isset INITNUMBER argument, if not, set 1 | INITNUMBER is the first number after renaming
if [ -z "$2" ]
    then i=1;
else
    i=$2;
fi

# counts the files to set leading zeros before number | max 1000 files
count=$(ls -l * | wc -l)
if [ $count -lt 10 ]
    then zeros=1;
else
    if [ $count -lt 100 ]
        then zeros=2;
    else
        zeros=3
    fi
fi

# rename script
for file in *
do
    mv $file $1_$(printf %0"$zeros"d.%s ${i%.*} ${file##*.})
    let i="$i+1"
done

0

Tôi biết có câu trả lời tuyệt vời ở đây nhưng tôi không tìm thấy tài liệu tham khảo nào để xử lý phần mở rộng tên tệp khi thêm hậu tố.

Tôi cần thêm hậu tố '_en' vào tất cả wavcác tệp trong thư mục trước phần mở rộng tệp.

Điều kỳ diệu là ở đây: %.*

for filename in *.wav; do mv $filename ${filename%.*}_en.wav; done;

Nếu bạn cần xử lý các phần mở rộng tệp khác nhau, hãy chọn câu trả lời này . Ít trực quan hơn một chút.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.