Rename Multiple Files - Linux/Ubuntu

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

Ubuntu: Rename multiple files in different directory

If you run this command, it will use GNU Parallel to start a new bashshell in each of the directories in parallel, and run ls in each one in parallel independently:

parallel --dry-run -k 'cd {} && ls' ::: */

Sample Output

cd Dir01/ && ls
cd Dir02/ && ls
cd Dir78/ && ls

If you remove the --dry-run it will do it for real.

So, instead of running ls, let's now look at using the rename command in each of the directories. The following will rename all the files in a directory with sequentially increasing numbers ($N):

rename --dry-run '$_=$N' *

Sample Output

'file87' would be renamed to '1'
'file88' would be renamed to '2'
'file89' would be renamed to '3'
'fred' would be renamed to '4'

All the foregoing suggests the command you want would be:

parallel --dry-run -k 'cd {} && rename --dry-run "s/.*/{#}_\$N/" *' ::: */

You can run it as it is and it will just show you what it is going to do, without actually doing anything.

If you like the look of that, remove the first --dry-run and run it again and it will actually go into each subdirectory and do a dry-run of the rename, again without actually changing anything.

If you still like the look of the command, make a small copy of your files somewhere in a temporary directory and try removing both the --dry-run parameters ands if it lives up to your needs.

Batch copy and rename multiple files in the same directory

There are going to be a lot of ways to slice-n-dice this one ...

One idea using a for loop, printf + brace expansion, and xargs:

for f in 01*.sh
do
printf "%s\n" {02..05} | xargs -r -I PFX cp ${f} PFX${f:2}
done

The same thing but saving the printf in a variable up front:

printf -v prefixes "%s\n" {02..05}

for f in 01*.sh
do
<<< "${prefixes}" xargs -r -I PFX cp ${f} PFX${f:2}
done

Another idea using a pair of for loops:

for f in 01*.sh
do
for i in {02..05}
do
cp "${f}" "${i}${f:2}"
done
done

Starting with:

$ ls -1 0*.sh
01a_AAA_qwe.sh
01b_AAA_asd.sh
01c_AAA_zxc.sh
01d_AAA_rty.sh

All of the proposed code snippets leave us with:

$ ls -1 0*.sh
01a_AAA_qwe.sh
01b_AAA_asd.sh
01c_AAA_zxc.sh
01d_AAA_rty.sh

02a_AAA_qwe.sh
02b_AAA_asd.sh
02c_AAA_zxc.sh
02d_AAA_rty.sh

03a_AAA_qwe.sh
03b_AAA_asd.sh
03c_AAA_zxc.sh
03d_AAA_rty.sh

04a_AAA_qwe.sh
04b_AAA_asd.sh
04c_AAA_zxc.sh
04d_AAA_rty.sh

05a_AAA_qwe.sh
05b_AAA_asd.sh
05c_AAA_zxc.sh
05d_AAA_rty.sh

NOTE: blank lines added for readability

Renaming files in a folder to sequential numbers

Try to use a loop, let, and printf for the padding:

a=1
for i in *.jpg; do
new=$(printf "%04d.jpg" "$a") #04 pad to length of 4
mv -i -- "$i" "$new"
let a=a+1
done

using the -i flag prevents automatically overwriting existing files, and using -- prevents mv from interpreting filenames with dashes as options.

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.



Related Topics



Leave a reply



Submit