Rename Multiple Files in Bash

Rename multiple files in shell

I like mmv for this kind of thing

mmv 'linux_*' '#1'

But you can also use rename. Be aware that there are commonly two rename commands with very different syntax. One is written in Perl, the other is distributed with util-linux, so I distinguish them as "perl rename" and "util rename" below.

With Perl rename:

rename 's/^linux_//' linux_*.mp4

As cweiske correctly pointed out.

With util rename:

rename linux_ '' linux_*.mp4

How can you tell which rename you have? Try running rename -V; if your version is util rename it will print the version number and if it is perl rename it will harmlessly report and unknown option and show usage.

If you don't have either rename or mmv and don't want to or can't install them you can still accomplish this with plain old shell code:

for file in linux_*.mp4 ; do mv "$file" "${file#linux_}" ; done

This syntax will work with any POSIX sh conforming to XPG4 or later, which is essentially all shells these days.

Rename multiple files in Bash with random strings

quickest hack to get a random-letters string I can think of is

head -c24 /dev/urandom | base64 | tr -dc a-zA-Z

so

randomname() { head -c24 /dev/urandom | base64 | tr -dc a-zA-Z; }
for f in file*.txt; do mv "$f" `randomname`.txt; done

and your odds of a collision are down in the one-in-a-billion range even with a huge list. Add a serial number on the end of randomname's output and that goes away too.

How to rename multiple files in several folders?

There are a thousand ways to do it, I'd do it with Perl, something like this will work:

find files -type f -name "file*" | perl -ne 'chomp; $f=$_; $f=~s/\/file/\/doc/; `mv $_  $f`;'
  • -ne process as inline script for each line input
  • chomp clean a newline
  • $f is new filename, same as old filename
  • s/\/file/\/doc/ replace "/file" with "/doc" in the new filename
  • mv $_ $f rename the file by running an OS command with back ticks

How to rename multiple files?

shopt -s extglob

for f in *; do
echo "$f: ${f/_*(0)/}"
# mv "$f" "${f/_*(0)/}" # for the actual rename
done

output

F_001_4837_blabla1.doc: F1_4837_blabla1.doc
F_045_8987_blabla2.doc: F45_8987_blabla2.doc
F_168_9092_blabla3.doc: F168_9092_blabla3.doc

Parameter Expansion

Parameter expansion can be used to replace the content of a variable. In this case, we replace the pattern _*(0) with nothing.

${parameter/pattern/string}
Pattern substitution. The pattern is expanded to produce a pat-
tern just as in pathname expansion. Parameter is expanded and
the longest match of pattern against its value is replaced with
string. If pattern begins with /, all matches of pattern are
replaced with string. Normally only the first match is
replaced. If pattern begins with #, it must match at the begin-
ning of the expanded value of parameter. If pattern begins with
%, it must match at the end of the expanded value of parameter.
If string is null, matches of pattern are deleted and the / fol-
lowing pattern may be omitted. If parameter is @ or *, the sub-
stitution operation is applied to each positional parameter in
turn, and the expansion is the resultant list. If parameter is
an array variable subscripted with @ or *, the substitution
operation is applied to each member of the array in turn, and
the expansion is the resultant list.

Extended pattern matching

Extended pattern matching allows us to use the pattern *(0) to match zero or more 0 characters. It needs to be enabled using the extglob setting.

If the extglob shell option is enabled using the shopt builtin, several
extended pattern matching operators are recognized. In the following
description, a pattern-list is a list of one or more patterns separated
by a |. Composite patterns may be formed using one or more of the fol-
lowing sub-patterns:

?(pattern-list)
Matches zero or one occurrence of the given patterns
*(pattern-list)
Matches zero or more occurrences of the given patterns
+(pattern-list)
Matches one or more occurrences of the given patterns
@(pattern-list)
Matches one of the given patterns
!(pattern-list)
Matches anything except one of the given patterns

Rename multiple files in bash

How about

rename 's/(.*).js/_$1/' *.js

Check the syntax for rename on your system.

The above command will rename A.js to _A & so on.

If you want to retain the extension, below should help:

rename 's/(.*)/_$1/' *.js

Renaming multiple files using shell script

Try something like this:

#! /bin/bash
declare -i i=0
for f in *.csv.gz; do
: $((i++))
mv "$f" "$(printf "FILE%03d_%s.csv.gz" $i "$(date +%Y%m%d)")"
done

You can pass the names of the files into the script. In that case you have to use dirname to get the name of the directory of each file.

#! /bin/bash
declare -i i=0
for f in "$@"; do
: $((i++))
mv "$f" "$(dirname "$f")"/"$(printf "FILE%03d_%s.csv.gz" $i "$(date +%Y%m%d)")"
done

Example:

$ mkdir {1,2,3}
$ touch {1,2,3}/{a,b,c}.csv.gz
$ ./rename.sh {1,2,3}/*.csv.gz
$ ls {1,2,3}
1:
FILE001_20211012.csv.gz FILE002_20211012.csv.gz FILE003_20211012.csv.gz

2:
FILE004_20211012.csv.gz FILE005_20211012.csv.gz FILE006_20211012.csv.gz

3:
FILE007_20211012.csv.gz FILE008_20211012.csv.gz FILE009_20211012.csv.gz


Related Topics



Leave a reply



Submit