简体   繁体   中英

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?

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.

如果您renamerename 's/^.*-doc-/doc-/' *.txt应该可以解决问题。

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 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 )

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
mmv "*-doc-*" "doc-#2"

mmv 命令代表“大规模移动”

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM