Shell/Bash shortcut for bulk renaming of files in a folder

Is there a shortcut in Shell/Bash that can rename all the files in a folder based on a regex or some other criteria. What I am looking for here is in my folder documents, that has let's say a 100 text files with the following naming convention:

<longdocumentidentifier>-doc-<counter>.txt.

I need to rename all the files with the above given convention to just:

doc-<counter>.txt

Is there a one-liner that can help me with the above?

53928 次浏览

The rename command built in to most linux, eg, will do this easily.

Personally, I prefer regexps too which is why I've been carrying around this script for a very very very long time (read: since the late 80s or early 90s):

#!/usr/bin/perl


($op = shift) || die "Usage: $0 expr [files]]\n";


if(!@ARGV)
{
@ARGV = <STDIN>;
chop(@ARGV);
}


for (@ARGV)
{
$was = $_;
eval $op;
die $@ if $@;


if ($was ne $_)
{
print "rename($was,$_)\n";
rename($was,$_);
}
}

Which, when installed lets you do things like this:

script-name 's/.*-doc(.*).txt/doc$1.txt/' *.txt

I would suggest something like this:

for i in *-doc-*.txt; do mv "$i" "${i/*-doc-/doc-}"; done

${i/*-doc-/doc-} replaces the first occurrence of *-doc- with doc-.

If you need to do more than one replacement (see comment number 1), you need to use the ${var//Pattern/Replacement} variant. If you need to replace the beginning of the name you need to use ${var/#Pattern/Replacement}, if you need to replace the end (ie: the extension) you need to use the ${var/%Pattern/Replacement} form.

See Shell Parameter Expansion for more details. This expansion is bash specific.

There is prename, that allows you to use REGEX:

prename 's/^.*-doc-(.*\.txt)$/doc-$1/'  *.txt

Use the option -n to simulate:

prename -n 's/^.*-doc-(.*\.txt)$/doc-$1/'  *.txt

Note: This is the shipped as rename in many Linux distributions, but not in all of them -- so I'm using the canonical name for the utility that comes with Perl.

If you have rename then, rename 's/^.*-doc-/doc-/' *.txt should do the trick.

mmv "*-doc-*" "doc-#2"

mmv command stands for "mass move"

If you want to recurse into sub-directories, there is also:

find . -maxdepth N -type f -name "$pattern" | sed -e 'p' -E -e "s/$str1/$str2/g" | xargs -n2 mv

On system that automatically support extended Regexps, you can leave away the -E.

Advantages:

  • recurses into sub-directories
  • you can control the maxdepth of the recursion
  • you can rename files and/or directories (-type f|d)

Disadvantages:

  • slightly more complicated regexps, because you have to strip out the path to get at the file name

(answer amended from here)

If you don't mind external tool, then here's one: rnm (web page)

For your particular problem the command would be:

rnm -rs '/.*-doc-/doc-/' *.txt

Or

rnm -rs '/.*-(doc-.*\.txt)/\1/' *.txt

You can find more examples/docs here.

find . -name '*scss' | xargs -L1 -I {} echo {} {} | sed 's/css.scss$/scss/' | xargs -L1 mv

for example if you have a bunch of files ending with ".css.scss" and you want to rename them to end with simply ".scss" (ie remove the .css part)

tweak the regexp and find arguments to your needs