Как переименовать с префиксом/суффиксом?

Как мне сделать mv original.filename new.original.filename без повторного ввода исходного имени файла?

Я бы предположил, что смогу сделать что-то вроде mv -p=new. original.filename или, возможно, mv original.filename new.~ или что-то еще, но я не вижу ничего подобного после просмотра man mv / info mv страниц.

Конечно, я мог бы написать сценарий оболочки для этого, но разве для этого не существует команды/флага?


person Peter Boughton    schedule 16.10.2008    source источник


Ответы (10)


В Bash и zsh это можно сделать с помощью расширения скобок. . Это просто расширяет список элементов в фигурных скобках. Например:

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

Таким образом, вы можете сделать свое переименование следующим образом:

mv {,new.}original.filename

поскольку это расширяется до:

mv original.filename new.original.filename
person Dave Webb    schedule 16.10.2008
comment
Спасибо, это похоже на лучшее решение - также работает с ksh. - person Peter Boughton; 16.10.2008
comment
Чего это не делает, так это работы с подстановочными знаками. То есть в каталоге, содержащем имена файлов a, b, c, использование echo {,new.}* дает список a b c new.* (поскольку генерация имени файла с помощью раскрытия фигурных скобок происходит до раскрытия подстановочных знаков - по крайней мере, путем вывода). - person Jonathan Leffler; 16.10.2008
comment
Уже несколько месяцев я ищу такое решение, используя только базовые функции оболочки... Я бы никогда не придумал что-то настолько простое, большое спасибо! - person flonk; 28.04.2014
comment
Спасибо за ссылку на Brace Expansion :-) именно то, что я искал! - person Pim Hazebroek; 02.08.2017
comment
Я люблю пример. У меня сейчас настроение пойти в Баскин Роббинс во время обеденного перерыва. - person Sridhar Sarnobat; 21.12.2017
comment
Серьезный вопрос, однако - какая строка .bashrc вам нужна, чтобы получить завершение табуляции, чтобы развернуть ее, чтобы вы могли видеть, что вы действительно собираетесь выполнить. - person Sridhar Sarnobat; 21.12.2017

Вы можете использовать команду rename(1):

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

Редактировать: если rename недоступен и вам нужно переименовать более одного файла, сценарий оболочки для этого может быть коротким и простым. Например, чтобы переименовать все *.jpg в prefix_*.jpg в текущем каталоге:

for filename in *.jpg; do mv "$filename" "prefix_$filename"; done;
person Simon Lehmann    schedule 16.10.2008
comment
Установил графит на этих выходных, и у них есть важный шаг (скопируйте все файлы *.example в папку conf, удалив суффикс примера). Очень ленивые с их стороны, но rename 's/(.*).example/$1/' *.example спасли меня от скуки. - person Conrad.Dean; 30.06.2013
comment
Это лучший ответ на данный момент. - person lifeisfoo; 05.01.2016
comment
Я не думаю, что вам нужен первый $ в этом сценарии. Так что просто 's/(.*)/new.$1/' - person wisbucky; 02.03.2018
comment
Команда rename не работает на моем компьютере с RHEL 6. Существуют ли разные версии этой команды? for ... done работал на меня. - person robsch; 05.04.2019

Вы можете добиться совместимого с unix переименования нескольких файлов (с использованием подстановочных знаков), создав цикл for:

for file in *; do
  mv $file new.${file%%}
done
person A Muguro    schedule 18.11.2012
comment
В чем разница между этим и на что уже ответил Саймон Леманн? - person Peter Boughton; 18.11.2012
comment
Это прекрасно работает. Что делает ${file%%}? Похоже на просто ${file} - person Sidmitra; 14.04.2015
comment
Меня тоже интересует ${file%%} - person Lucas Bustamante; 11.08.2018
comment
Для меня %% выглядит как ошибка - person Asteroids With Wings; 10.12.2020

Я видел, как люди упоминали команду rename, но она обычно недоступна в системах Unix (в отличие, скажем, от систем Linux или Cygwin, где rename является исполняемым файлом, а не сценарием). Эта версия rename имеет довольно ограниченную функциональность:

rename from to file ...

Он заменяет часть имени файла from на to, и пример, приведенный на справочной странице:

rename foo foo0 foo? foo??

Это переименовывает foo1 в foo01, foo10 в foo010 и т. д.

Я использую Perl-скрипт под названием rename, который я изначально выкопал из первого издания книги Camel, примерно 1992 года, а затем расширил его для переименования файлов.

#!/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";
    }
}

Это позволяет вам написать любую команду замены или транслитерации Perl для сопоставления имен файлов. В конкретном запрошенном примере вы должны использовать:

rename 's/^/new./' original.filename
person Jonathan Leffler    schedule 16.10.2008
comment
Спасибо, если бы я мог принять второй ответ, это был бы он. Мне нужна стандартная команда, которая будет работать со всем, что я могу использовать, но я могу поставить этот скрипт на машины, которые я часто использую, и он все равно будет полезен. - person Peter Boughton; 16.10.2008
comment
Джеймс Вонг отмечает, что для Arch Linux вы можете просто загрузить и установить этот скрипт через pacman, используя: pacman -Sy perl-rename. Затем добавьте к нему псевдоним в вашем bashrc: alias rename='perl-rename' - person Jonathan Leffler; 15.01.2017
comment
что, если from или to являются пустыми строками, то есть вы хотите добавить что-то к каждому имени файла или полностью удалить что-то - person Troyseph; 04.10.2019
comment
@Troyseph — чтобы добавить '.html к именам файлов, используйте 's/$/.html/' — чтобы удалить tmp отовсюду в именах файлов, используйте 's/tmp//g' (найдите tmp и замените везде ничем). - person Jonathan Leffler; 04.10.2019

Самый простой способ массового переименования файлов в каталоге:

ls | xargs -I fileName mv fileName fileName.suffix
person Brajan Elektro    schedule 23.11.2018

Я знаю, что здесь есть отличные ответы, но я не нашел ссылок на обработку расширений имен файлов при добавлении суффикса.

Мне нужно было добавить суффикс «_en» ко всем файлам wav в папке перед расширением файла.

Волшебство здесь: %.*

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

Если вам нужно обрабатывать файлы с разными расширениями, проверьте этот ответ. Чуть менее интуитивным.

person yeya    schedule 22.06.2020

Если он открыт для модификации, вы можете использовать суффикс вместо префикса. Затем вы можете использовать табуляцию, чтобы получить исходное имя файла и добавить суффикс.

В противном случае нет, это не то, что поддерживается командой mv. Однако простой сценарий оболочки может справиться.

person workmad3    schedule 16.10.2008
comment
Часто мне нужно и то, и другое, но в первую очередь префикс - как вы говорите, завершение табуляции может обрабатывать суффиксы. - person Peter Boughton; 16.10.2008

В моем случае у меня есть группа файлов, которые нужно переименовать, прежде чем я смогу с ними работать. Каждый файл имеет свою роль в группе и имеет свой шаблон.

В результате у меня есть список команд переименования, например:

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

Попробуйте это также:

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

Это создаст все комбинации с префиксами и суффиксами:

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

Другой способ решить ту же проблему — создать массив сопоставления и добавить соответствующий префикс для каждого типа файла, как показано ниже:

#!/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
person aprodan    schedule 26.01.2016

Массовое переименование файлов bash-скрипт

#!/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
person Harkály Gergő    schedule 05.03.2016

Мне не нравится ни один из ответов. Я считаю, что вам нужен раствор ванильного баша. Так вот!

Сначала попробуйте это с эхом, чтобы увидеть, что произойдет! Проверьте свою команду, прежде чем использовать ее на тысячах файлов!

Удалите './', если вы хотите поставить префикс find . -type f -exec bash -c 'echo prefix_${0#./}' {} \;

Удалите расширение, если хотите добавить что-то после него find . -type f -exec bash -c 'echo ${0%.*}_suffix.${0##*.}' {} \;

Теперь, чтобы использовать это для переименования, просто замените echo на mv $0

ПРИМЕР: find . -type f -exec bash -c 'mv $0 1.${0#./}' {} \;

Источник вдохновения: https://gist.github.com/larshaendler/723d2ec447c3c694b71dc6e3bc3aadc9

person botenvouwer    schedule 03.04.2021